代码改变世界

跨平台轻量级读写锁

2015-07-21 16:41  哦万里云  阅读(448)  评论(0编辑  收藏  举报

锁的数据结构足够简单: volatile long;

将long的最高位存放写锁标志,低24位作为读锁计数;

写锁的实现:

1.加锁时,等待long位0时设置写锁标志,用原子操作实现。可以保证加锁前没有任何人获得读锁或写锁;

2.解锁时,去掉写锁标志;

读锁的实现:

1.加锁时,首先增加读锁计数,于是释放前任何写锁都会失败。然后等待写锁释放(如果有);

2.解锁时,减少读锁计数;

 

保证,任意时刻

1.加了一个写锁(没有任何读锁)

2.或者同时加多个读锁(没有任何写锁)

 

头文件;

#ifndef _MY_ATOMIC_H_
#define _MY_ATOMIC_H_


class ReadLock
{
public:
    ReadLock(volatile long  & lock);
    ~ReadLock();
private:
    ReadLock(const ReadLock & );
    ReadLock & operator = (const ReadLock & );
private:
    volatile long & m_lock;
};

class WriteLock
{
public:
    WriteLock(volatile long  & lock);
    ~WriteLock();
private:
    WriteLock(const WriteLock & );
    WriteLock & operator = (const WriteLock & );
private:
    volatile long & m_lock;
};

#endif

头文件;

#include "Atomic.h"

static union{ char c[4];unsigned long myLong;} test_union = { { 'L','?','?','B'} };
#define ENDIANNESS  ((char)test_union.myLong)


void MyLockedAdd(volatile long & dst,long val)
{
#ifdef WIN32
    InterlockedExchangeAdd(&dst,val);
#else
    __sync_add_and_fetch(&dst,val);
#endif
}

bool MyLockedCompareSwap(volatile long & dst,long val,long cmp)
{
#ifdef WIN32
    return cmp == InterlockedCompareExchange(&dst,val,cmp);
#else
    return __sync_bool_compare_and_swap (&dst,cmp,val);
#endif

}

const long WRITE_LOCK_VALUE = 1<<24; 
ReadLock::ReadLock(volatile long & lock):m_lock(lock)
{
    MyLockedAdd(m_lock,1);

    volatile char * pWL = (volatile char *)&m_lock;
    if(ENDIANNESS == 'L')
        pWL += 3;
    for(;*pWL;)
        ;
}

ReadLock::~ReadLock()
{
    MyLockedAdd(m_lock,-1);
}

WriteLock::WriteLock(volatile long & lock):m_lock(lock)
{
    while(!MyLockedCompareSwap(m_lock,WRITE_LOCK_VALUE,0))
        ;
}

WriteLock::~WriteLock()
{
    MyLockedAdd(m_lock,-WRITE_LOCK_VALUE);
}