/[svn]/linuxsampler/trunk/src/common/SynchronizedConfig.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/common/SynchronizedConfig.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1789 by persson, Sat Jan 19 16:55:03 2008 UTC revision 1790 by persson, Sun Nov 2 12:05:00 2008 UTC
# Line 18  Line 18 
18   *   MA  02110-1301  USA                                                   *   *   MA  02110-1301  USA                                                   *
19   ***************************************************************************/   ***************************************************************************/
20    
21  #ifndef __SYNCHRONIZEDCONFIG_H__  #ifndef SYNCHRONIZEDCONFIG_H
22  #define __SYNCHRONIZEDCONFIG_H__  #define SYNCHRONIZEDCONFIG_H
23    
24  #include <set>  #include <set>
25    #include <unistd.h>
26    #include "lsatomic.h"
27    
28  namespace LinuxSampler {  namespace LinuxSampler {
29    
# Line 47  namespace LinuxSampler { Line 49  namespace LinuxSampler {
49       */       */
50      template<class T>      template<class T>
51      class SynchronizedConfig {      class SynchronizedConfig {
         struct atomic_t { volatile int word; };  
   
52          public:          public:
53              SynchronizedConfig();              SynchronizedConfig();
54    
# Line 66  namespace LinuxSampler { Line 66  namespace LinuxSampler {
66                       *          thread                       *          thread
67                       */                       */
68                      const T& Lock() {                      const T& Lock() {
69                          atomicSet(&lock, 1);                          lock.store(1, memory_order_relaxed);
70                          return parent.config[atomicRead(&parent.indexAtomic)];                          atomic_thread_fence(memory_order_seq_cst);
71                            return parent.config[parent.indexAtomic.load(
72                                    memory_order_acquire)];
73                      }                      }
74    
75                      /**                      /**
# Line 79  namespace LinuxSampler { Line 81  namespace LinuxSampler {
81                       * time threads are locked anymore.                       * time threads are locked anymore.
82                       */                       */
83                      void Unlock() {                      void Unlock() {
84                          atomicSet(&flag, 0);                          atomic_thread_fence(memory_order_release);
85                          atomicSet(&lock, 0);                          lock.store(0, memory_order_relaxed);
86                            flag.store(0, memory_order_relaxed);
87                      }                      }
88    
89                      Reader(SynchronizedConfig& config);                      Reader(SynchronizedConfig& config);
# Line 88  namespace LinuxSampler { Line 91  namespace LinuxSampler {
91                  private:                  private:
92                      friend class SynchronizedConfig;                      friend class SynchronizedConfig;
93                      SynchronizedConfig& parent;                      SynchronizedConfig& parent;
94                      atomic_t lock;                      atomic<int> lock;
95                      atomic_t flag;                      atomic<int> flag;
96                      Reader *next; // only used locally in SwitchConfig                      Reader *next; // only used locally in SwitchConfig
97              };              };
98    
# Line 123  namespace LinuxSampler { Line 126  namespace LinuxSampler {
126              T& SwitchConfig();              T& SwitchConfig();
127    
128          private:          private:
129              atomic_t indexAtomic;              atomic<int> indexAtomic;
130              int updateIndex;              int updateIndex;
131              T config[2];              T config[2];
132              std::set<Reader*> readers;              std::set<Reader*> readers;
   
             static int atomicRead(atomic_t* pSharedVariable) {  
                 return pSharedVariable->word;  
             }  
   
             static void atomicSet(atomic_t* pSharedVariable, int value) {  
                 pSharedVariable->word = value;  
             }  
133      };      };
134    
135      template<class T> SynchronizedConfig<T>::SynchronizedConfig() {      template<class T> SynchronizedConfig<T>::SynchronizedConfig() :
136          atomicSet(&indexAtomic, 0);          indexAtomic(0) {
137          updateIndex = 1;          updateIndex = 1;
138      }      }
139    
# Line 147  namespace LinuxSampler { Line 142  namespace LinuxSampler {
142      }      }
143    
144      template<class T> T& SynchronizedConfig<T>::SwitchConfig() {      template<class T> T& SynchronizedConfig<T>::SwitchConfig() {
145          atomicSet(&indexAtomic, updateIndex);          indexAtomic.store(updateIndex, memory_order_release);
146            atomic_thread_fence(memory_order_seq_cst);
147    
148          // first put all locking readers in a linked list          // first put all locking readers in a linked list
149          Reader* lockingReaders = 0;          Reader* lockingReaders = 0;
150          for (typename std::set<Reader*>::iterator iter = readers.begin() ;          for (typename std::set<Reader*>::iterator iter = readers.begin() ;
151               iter != readers.end() ;               iter != readers.end() ;
152               iter++) {               iter++) {
153              atomicSet(&(*iter)->flag, 1);              (*iter)->flag.store(1, memory_order_relaxed);
154              if (atomicRead(&(*iter)->lock) && atomicRead(&(*iter)->flag)) {              if ((*iter)->lock.load(memory_order_acquire) &&
155                    (*iter)->flag.load(memory_order_acquire)) {
156                  (*iter)->next = lockingReaders;                  (*iter)->next = lockingReaders;
157                  lockingReaders = *iter;                  lockingReaders = *iter;
158              }              }
# Line 166  namespace LinuxSampler { Line 163  namespace LinuxSampler {
163              usleep(50000);              usleep(50000);
164              Reader** prev = &lockingReaders;              Reader** prev = &lockingReaders;
165              for (Reader* p = lockingReaders ; p ; p = p->next) {              for (Reader* p = lockingReaders ; p ; p = p->next) {
166                  if (atomicRead(&p->lock) && atomicRead(&p->flag)) prev = &p->next;                 if (p->lock.load(memory_order_acquire) &&
167                       p->flag.load(memory_order_acquire)) prev = &p->next;
168                  else *prev = p->next; // unlink                  else *prev = p->next; // unlink
169              }              }
170          }          }
# Line 179  namespace LinuxSampler { Line 177  namespace LinuxSampler {
177      // ----- Reader ----      // ----- Reader ----
178    
179      template <class T>      template <class T>
180      SynchronizedConfig<T>::Reader::Reader(SynchronizedConfig& config) : parent(config) {      SynchronizedConfig<T>::Reader::Reader(SynchronizedConfig& config) :
181          atomicSet(&lock, 0);          parent(config), lock(0), flag(0) {
182          parent.readers.insert(this);          parent.readers.insert(this);
183      }      }
184    

Legend:
Removed from v.1789  
changed lines
  Added in v.1790

  ViewVC Help
Powered by ViewVC