double-locked singleton (spinlock version)

static inline int 		// return old value
atomic_add(volatile int *count, int add)
{
#ifdef __linux__
	__asm__ __volatile__(
		"lock xadd %0, (%1);"
		: "=a"(add)
		: "r"(count), "a"(add)
		: "memory"
	);
#else
#error "not done yet "
#endif
	return add;
}

static inline int 		// return old value
atomic_swap(volatile void *lockword, int value)
{
#ifdef __linux__
    __asm__ __volatile__(
        "lock xchg %0, (%1);"
        : "=a"(value)
        : "r"(lockword), "a"(value)
        : "memory"
        );
#else
#error "not done yet "
#endif
    return value;
}

static inline int 		// return old value
atomic_comp_swap(volatile void *lockword, 
                  int exchange,  
                  int comperand)
{
#ifdef __linux__
    __asm__ __volatile__(
        "lock cmpxchg %1, (%2)"
        :"=a"(comperand)
        :"d"(exchange), "r"(lockword), "a"(comperand) 
        );
#else
    __asm {
        mov eax, comperand
        mov edx, exchange
        mov ecx, lockword
        lock cmpxchg [ecx], edx
        mov comperand, eax
    }
#endif /* #ifdef __linux__ */
    return comperand;
}
static inline void 
spin_lock(volatile int *lock)
{
	int l;
	int i = 10;
	int id = thread_getid();
	for (l=atomic_comp_swap(lock, id, 0);
		l!=0 && l!=id; 
		l=atomic_comp_swap(lock, id, 0)
	) {
		if (i --) { 
			nop(); 
		} 
		else { 
			i = 10; 
			thread_yield();
		}
	}
}

static inline bool
spin_unlock(volatile int *lock)
{
	int id = thread_getid();
	return id == atomic_comp_swap(lock, 0, id);
}

static inline bool 
spin_trylock(volatile int *lock)
{
	int id = thread_getid();
	int owner = atomic_comp_swap(lock, id, 0);
	return (owner==0 || owner==id);
}

static inline int
token_acquire(volatile int *token, int id)
{
	return atomic_comp_swap(token, id, 0);
}

static inline int
token_release(volatile int *token, int id)
{
	return atomic_comp_swap(token, 0, id);
}

static inline int
token_transfer(volatile int *token, int oldid, int newid)
{
	return atomic_comp_swap(token, newid, oldid);
}

static inline int
token_set(volatile int *token, int id)
{
    return atomic_comp_swap(token, id, *token);
}

#define DECLARE_SINGLETON(classname)                            \
    public:                                                     \
        static classname * Instance() {                         \
            if (NULL != sm_pInstance) {                         \
                return sm_pInstance;                            \
            }                                                   \
            spin_lock(&sm_lock);                                \
            if (NULL == sm_pInstance) {                         \
                sm_pInstance = new classname();                 \
            }                                                   \
            spin_unlock(&sm_lock);                              \
            return sm_pInstance;                                \
        }                                                       \
        static bool IsCreated() {                               \
            bool b;                                             \
            spin_lock(&sm_lock);                                \
            b = (NULL != sm_pInstance);                         \
            spin_unlock(&sm_lock);                              \
            return b;                                           \
        }                                                       \
    protected:                                                  \
        classname();                                            \
        static classname * sm_pInstance;                        \
        static volatile int sm_lock;                            \
    private: 


#define IMPLEMENT_SINGLETON(classname)                          \
    classname* classname::sm_pInstance = NULL;                  \
    volatile int classname::sm_lock = 0;                        \
    classname::classname() {}


#define IMPLEMENT_SINGLETON_WITHOUT_CTOR(classname)             \
    volatile int classname::sm_lock = 0;                        \
    classname * classname::sm_pInstance = NULL;


你可能感兴趣的:(c++,baidu生活,Linux,token,exchange,thread,null,linux)