--- linuxsampler/trunk/src/common/SynchronizedConfig.h 2008/01/19 16:55:03 1644 +++ linuxsampler/trunk/src/common/SynchronizedConfig.h 2008/11/02 12:05:00 1790 @@ -18,10 +18,12 @@ * MA 02110-1301 USA * ***************************************************************************/ -#ifndef __SYNCHRONIZEDCONFIG_H__ -#define __SYNCHRONIZEDCONFIG_H__ +#ifndef SYNCHRONIZEDCONFIG_H +#define SYNCHRONIZEDCONFIG_H #include +#include +#include "lsatomic.h" namespace LinuxSampler { @@ -47,8 +49,6 @@ */ template class SynchronizedConfig { - struct atomic_t { volatile int word; }; - public: SynchronizedConfig(); @@ -66,8 +66,10 @@ * thread */ const T& Lock() { - atomicSet(&lock, 1); - return parent.config[atomicRead(&parent.indexAtomic)]; + lock.store(1, memory_order_relaxed); + atomic_thread_fence(memory_order_seq_cst); + return parent.config[parent.indexAtomic.load( + memory_order_acquire)]; } /** @@ -79,8 +81,9 @@ * time threads are locked anymore. */ void Unlock() { - atomicSet(&flag, 0); - atomicSet(&lock, 0); + atomic_thread_fence(memory_order_release); + lock.store(0, memory_order_relaxed); + flag.store(0, memory_order_relaxed); } Reader(SynchronizedConfig& config); @@ -88,8 +91,8 @@ private: friend class SynchronizedConfig; SynchronizedConfig& parent; - atomic_t lock; - atomic_t flag; + atomic lock; + atomic flag; Reader *next; // only used locally in SwitchConfig }; @@ -123,22 +126,14 @@ T& SwitchConfig(); private: - atomic_t indexAtomic; + atomic indexAtomic; int updateIndex; T config[2]; std::set readers; - - static int atomicRead(atomic_t* pSharedVariable) { - return pSharedVariable->word; - } - - static void atomicSet(atomic_t* pSharedVariable, int value) { - pSharedVariable->word = value; - } }; - template SynchronizedConfig::SynchronizedConfig() { - atomicSet(&indexAtomic, 0); + template SynchronizedConfig::SynchronizedConfig() : + indexAtomic(0) { updateIndex = 1; } @@ -147,15 +142,17 @@ } template T& SynchronizedConfig::SwitchConfig() { - atomicSet(&indexAtomic, updateIndex); + indexAtomic.store(updateIndex, memory_order_release); + atomic_thread_fence(memory_order_seq_cst); // first put all locking readers in a linked list Reader* lockingReaders = 0; for (typename std::set::iterator iter = readers.begin() ; iter != readers.end() ; iter++) { - atomicSet(&(*iter)->flag, 1); - if (atomicRead(&(*iter)->lock) && atomicRead(&(*iter)->flag)) { + (*iter)->flag.store(1, memory_order_relaxed); + if ((*iter)->lock.load(memory_order_acquire) && + (*iter)->flag.load(memory_order_acquire)) { (*iter)->next = lockingReaders; lockingReaders = *iter; } @@ -166,7 +163,8 @@ usleep(50000); Reader** prev = &lockingReaders; for (Reader* p = lockingReaders ; p ; p = p->next) { - if (atomicRead(&p->lock) && atomicRead(&p->flag)) prev = &p->next; + if (p->lock.load(memory_order_acquire) && + p->flag.load(memory_order_acquire)) prev = &p->next; else *prev = p->next; // unlink } } @@ -179,8 +177,8 @@ // ----- Reader ---- template - SynchronizedConfig::Reader::Reader(SynchronizedConfig& config) : parent(config) { - atomicSet(&lock, 0); + SynchronizedConfig::Reader::Reader(SynchronizedConfig& config) : + parent(config), lock(0), flag(0) { parent.readers.insert(this); }