c++ - Lightweight spinlocks built from GCC atomic operations? -


i'd minimize synchronization , write lock-free code when possible in project of mine. when absolutely necessary i'd love substitute light-weight spinlocks built atomic operations pthread , win32 mutex locks. understanding these system calls underneath , cause context switch (which may unnecessary quick critical sections spinning few times preferable).

the atomic operations i'm referring documented here: http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/atomic-builtins.html

here example illustrate i'm talking about. imagine rb-tree multiple readers , writers possible. rbtree::exists() read-only , thread safe, rbtree::insert() require exclusive access single writer (and no readers) safe. code:

class intsettest { private:     unsigned short lock;     rbtree<int>* myset;  public:     // ...      void add_number(int n)     {         // aquire once locked==false (atomic)         while (__sync_bool_compare_and_swap(&lock, 0, 0xffff) == false);          // perform thread-unsafe operation on set         myset->insert(n);          // unlock (atomic)         __sync_bool_compare_and_swap(&lock, 0xffff, 0);     }      bool check_number(int n)     {         // increment once lock below 0xffff         u16 savedlock = lock;         while (savedlock == 0xffff || __sync_bool_compare_and_swap(&lock, savedlock, savedlock+1) == false)             savedlock = lock;          // perform read-only operation             bool exists = tree->exists(n);          // decrement         savedlock = lock;         while (__sync_bool_compare_and_swap(&lock, savedlock, savedlock-1) == false)             savedlock = lock;          return exists;     } }; 

(lets assume need not exception-safe)

is code indeed thread-safe? there pros/cons idea? advice? use of spinlocks bad idea if threads not concurrent?

thanks in advance. ;)

you need volatile qualifier on lock, , make sig_atomic_t. without volatile qualifier, code:

    u16 savedlock = lock;     while (savedlock == 0xffff || __sync_bool_compare_and_swap(&lock, savedlock, savedlock+1) == false)         savedlock = lock; 

may not re-read lock when updating savedlock in body of while-loop. consider case lock 0xffff. then, savedlock 0xffff prior checking loop condition, while condition short-circuit prior calling __sync_bool_compare_and_swap. since __sync_bool_compare_and_swap wasn't called, compiler doesn't encounter memory barrier, might reasonably assume value of lock hasn't changed underneath you, , avoid re-loading in savedlock.

re: sig_atomic_t, there's decent discussion here. same considerations apply signal handlers apply threads.

with these changes, i'd guess code thread-safe. still recommend using mutexes, though, since don't know how long rb-tree insert take in general case (per previous comments under question).


Comments

Popular posts from this blog

javascript - Enclosure Memory Copies -

php - Replacing tags in braces, even nested tags, with regex -