A Small Spin Lock

#include <ctime>
#include <cstdlib>

class SmallSpinLock
{
    class Sleeper
    {
    public:
        Sleeper () : _spinCount (0)
        {

        }

        void wait()
        {
            if (_spinCount < kMaxActiveSpin) {
                ++_spinCount;
                asm volatile ("pause");
            }
            else {
                /*
                * Always sleep 0.2ms, assuming this will make the kernel put
                * us down for whatever its minimum timer resolution is (in
                * linux this varies by kernel version from 1ms to 10ms).
                */
                struct timespec ts = { 0, 200000 };
                nanosleep (&ts, NULL);
            }
        }

    private:
        Sleeper (const Sleeper&);
        Sleeper& operator= (const Sleeper&);

    private:
        uint32_t _spinCount;
        static const uint32_t kMaxActiveSpin = 8000;
    };

private:
    enum { FREE = 0, LOCKED = 1 };
    uint8_t _lock;

    /*
    * Atomically move _lock from "compare" to "newval". Return boolean
    * success. Do not play on or around.
    *
    * 拿comapre变量的值同_lock变量比较是否相等,如果相等则把newval的值赋给_lock,
    * 然后zf标志会被置位,并通过setz设置结果out。即当我们想获得锁的时候这样用:cas (0,1); 返回true表示成功。
    */
    bool cas (uint8_t compare, uint8_t newVal)
    {
        bool out;
        asm volatile ("lock; cmpxchgb %2, (%3);"
                "setz %0;"
                : "=r" (out)
                : "a" (compare), // cmpxchgb constrains this to be in %al
                "q" (newVal),    // Needs to be byte-accessible
                "r" (&_lock)
                : "memory", "flags");
        return out;
    }

    SmallSpinLock (const SmallSpinLock&);
    SmallSpinLock& operator= (const SmallSpinLock&);

public:
    SmallSpinLock ()
    {
        _lock = FREE;
    }

    ~SmallSpinLock ()
    {

    }

    bool try_lock ()
    {
        return cas (FREE, LOCKED);
    }

    void lock ()
    {
        Sleeper sleeper;
        do {
            while (_lock != FREE) {
                asm volatile ("" : : : "memory");
                sleeper.wait ();
            }
        } while (!try_lock ());
        assert (_lock == LOCKED);
    }

    void unlock ()
    {
        assert (_lock == LOCKED);
        asm volatile("" : : : "memory");
        _lock = FREE; // release barrier on x86
    }
};


注:

barrier内存栅栏 
#define barrier()  __asm__ __volatile__("": : :"memory")
 
1)__asm__用于指示编译器在此插入汇编语句
2)__volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。
3)memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。
4)"":::表示这是个空指令。

你可能感兴趣的:(A Small Spin Lock)