/[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 1038 by persson, Sat Feb 3 15:33:00 2007 UTC revision 1887 by persson, Sat Apr 18 08:17:16 2009 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2006 Andreas Persson                                    *   *   Copyright (C) 2006-2009 Andreas Persson                               *
4   *                                                                         *   *                                                                         *
5   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
6   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# 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    
 #include "atomic.h"  
24  #include <set>  #include <set>
25    #include <unistd.h>
26    #include "lsatomic.h"
27    
28  namespace LinuxSampler {  namespace LinuxSampler {
29    
# Line 65  namespace LinuxSampler { Line 66  namespace LinuxSampler {
66                       *          thread                       *          thread
67                       */                       */
68                      const T& Lock() {                      const T& Lock() {
69                          atomic_set(&lock, 1);                          lock.store(lockCount += 2, memory_order_relaxed);
70                          return parent.config[atomic_read(&parent.indexAtomic)];                          atomic_thread_fence(memory_order_seq_cst);
71                            return parent.config[parent.indexAtomic.load(
72                                    memory_order_acquire)];
73                      }                      }
74    
75                      /**                      /**
# Line 78  namespace LinuxSampler { Line 81  namespace LinuxSampler {
81                       * time threads are locked anymore.                       * time threads are locked anymore.
82                       */                       */
83                      void Unlock() {                      void Unlock() {
84                          atomic_set(&lock, 0);                          lock.store(0, memory_order_release);
85                      }                      }
86    
87                      Reader(SynchronizedConfig& config);                      Reader(SynchronizedConfig& config);
# Line 86  namespace LinuxSampler { Line 89  namespace LinuxSampler {
89                  private:                  private:
90                      friend class SynchronizedConfig;                      friend class SynchronizedConfig;
91                      SynchronizedConfig& parent;                      SynchronizedConfig& parent;
92                      atomic_t lock;                      int lockCount; // increased in every Lock(),
93                      Reader *next; // only used locally in SwitchConfig                                     // lowest bit is always set.
94                        atomic<int> lock; // equals lockCount when inside
95                                          // critical region, otherwise 0
96                        Reader* next; // only used locally in SwitchConfig
97                        int prevLock; // only used locally in SwitchConfig
98              };              };
99    
100    
# Line 120  namespace LinuxSampler { Line 127  namespace LinuxSampler {
127              T& SwitchConfig();              T& SwitchConfig();
128    
129          private:          private:
130              atomic_t indexAtomic;              atomic<int> indexAtomic;
131              int updateIndex;              int updateIndex;
132              T config[2];              T config[2];
133              std::set<Reader*> readers;              std::set<Reader*> readers;
134      };      };
135    
136      template<class T> SynchronizedConfig<T>::SynchronizedConfig() {      template<class T> SynchronizedConfig<T>::SynchronizedConfig() :
137          atomic_set(&indexAtomic, 0);          indexAtomic(0) {
138          updateIndex = 1;          updateIndex = 1;
139      }      }
140    
# Line 136  namespace LinuxSampler { Line 143  namespace LinuxSampler {
143      }      }
144    
145      template<class T> T& SynchronizedConfig<T>::SwitchConfig() {      template<class T> T& SynchronizedConfig<T>::SwitchConfig() {
146          atomic_set(&indexAtomic, updateIndex);          indexAtomic.store(updateIndex, memory_order_release);
147            atomic_thread_fence(memory_order_seq_cst);
148    
149          // first put all locking readers in a linked list          // first put all locking readers in a linked list
150          Reader* lockingReaders = 0;          Reader* lockingReaders = 0;
151          for (typename std::set<Reader*>::iterator iter = readers.begin() ;          for (typename std::set<Reader*>::iterator iter = readers.begin() ;
152               iter != readers.end() ;               iter != readers.end() ;
153               iter++) {               iter++) {
154              if (atomic_read(&(*iter)->lock)) {              (*iter)->prevLock = (*iter)->lock.load(memory_order_acquire);
155                if ((*iter)->prevLock) {
156                  (*iter)->next = lockingReaders;                  (*iter)->next = lockingReaders;
157                  lockingReaders = *iter;                  lockingReaders = *iter;
158              }              }
# Line 154  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 (atomic_read(&p->lock)) prev = &p->next;                  if (p->lock.load(memory_order_acquire) == p->prevLock) {
167                  else *prev = p->next; // unlink                      prev = &p->next;
168                    } else {
169                        *prev = p->next; // unlink
170                    }
171              }              }
172          }          }
173    
# Line 167  namespace LinuxSampler { Line 179  namespace LinuxSampler {
179      // ----- Reader ----      // ----- Reader ----
180    
181      template <class T>      template <class T>
182      SynchronizedConfig<T>::Reader::Reader(SynchronizedConfig& config) : parent(config) {      SynchronizedConfig<T>::Reader::Reader(SynchronizedConfig& config) :
183          atomic_set(&lock, 0);          parent(config), lock(0), lockCount(1) {
184          parent.readers.insert(this);          parent.readers.insert(this);
185      }      }
186    

Legend:
Removed from v.1038  
changed lines
  Added in v.1887

  ViewVC Help
Powered by ViewVC