/[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 2499 by schoenebeck, Mon May 13 19:11:08 2013 UTC revision 2500 by schoenebeck, Fri Jan 10 12:20:05 2014 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2006-2012 Andreas Persson                               *   *   Copyright (C) 2006-2014 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 123  namespace LinuxSampler { Line 123  namespace LinuxSampler {
123              T& GetConfigForUpdate();              T& GetConfigForUpdate();
124    
125              /**              /**
126                 * Get the data on update side <b>unprotected</b>, that is
127                 * <b>without</b> locking or any means of synchronizations.
128                 *
129                 * Due to its nature this must only be called for read access and
130                 * you have to make sure by yourself, that the data/member you
131                 * access is really safe for concurrent read access (i.e. SGI's
132                 * implementation of std::vector::size() would be safe).
133                 *
134                 * Only use this when you are absolutely sure what you are doing!
135                 */
136                const T& GetUnsafeUpdateConfig() const {
137                    return config[updateIndex];
138                }
139    
140                /**
141               * Atomically switch the newly updated configuration               * Atomically switch the newly updated configuration
142               * object with the one used by the real time thread, then               * object with the one used by the real time thread, then
143               * wait for the real time thread to finish working with               * wait for the real time thread to finish working with
# Line 226  namespace LinuxSampler { Line 241  namespace LinuxSampler {
241           *           *
242           * @return the shared protected data           * @return the shared protected data
243           */           */
244          virtual T& beginSync() = 0; //TODO: or call it lock() instead ?          virtual void beginSync() = 0; //TODO: or call it lock() instead ?
245                
246            /**
247             * Retrieve reference to critical, shared data. This method shall be
248             * called between a beginSync() and endSync() call pair, to be sure
249             * that shared data can be accessed safely.
250             */
251            virtual T& syncedData() = 0;
252    
253          /**          /**
254           * Signal that the synchronized code block has been left. Depending           * Signal that the synchronized code block has been left. Depending
255           * on the actual implementation, this call may block the calling           * on the actual implementation, this call may block the calling
# Line 251  namespace LinuxSampler { Line 273  namespace LinuxSampler {
273      public:      public:
274          Sync(Synchronizer<T>* syncer) {          Sync(Synchronizer<T>* syncer) {
275              this->syncer = syncer;              this->syncer = syncer;
276              this->data = &syncer->beginSync();              syncer->beginSync();
277          }          }
278                    
279          virtual ~Sync() {          virtual ~Sync() {
280              syncer->endSync();              syncer->endSync();
281          }          }
282                    
283          Sync& operator =(const Sync& arg) {          /*Sync& operator =(const Sync& arg) {
284              *this->data = *arg.data;              *this->data = *arg.data;
285              return *this;              return *this;
286          }          }*/
287    
288          Sync& operator =(const T& arg) {          /*Sync& operator =(const T& arg) {
289              *this->data = arg;              *this->data = arg;
290              return *this;              return *this;
291          }          }*/
292                    
293          const T& operator *() const { return *data; }          const T& operator *() const { return syncer->syncedData(); }
294          T&       operator *()       { return *data; }          T&       operator *()       { return syncer->syncedData(); }
295    
296          const T* operator ->() const { return data; }          const T* operator ->() const { return &syncer->syncedData(); }
297          T*       operator ->()       { return data; }          T*       operator ->()       { return &syncer->syncedData(); }
298    
299      private:      private:
300          Synchronizer<T>* syncer; ///< Points to the object that shall be responsible to protect the shared data.          Synchronizer<T>* syncer; ///< Points to the object that shall be responsible to protect the shared data.
         T* data; ///< Points to the shared data that should be protected.  
301      };      };
302    
303      /**      /**
# Line 289  namespace LinuxSampler { Line 310  namespace LinuxSampler {
310      template<class T>      template<class T>
311      class BackBuffer : public SynchronizedConfig<T>, public Synchronizer<T> {      class BackBuffer : public SynchronizedConfig<T>, public Synchronizer<T> {
312      public:      public:
313          virtual T& beginSync() OVERRIDE {          virtual void beginSync() OVERRIDE {
314              mutex.Lock();              mutex.Lock();
315              data = &SynchronizedConfig<T>::GetConfigForUpdate();          }
316              return *data;          
317            virtual T& syncedData() OVERRIDE {
318                return SynchronizedConfig<T>::GetConfigForUpdate();
319          }          }
320    
321          virtual void endSync() OVERRIDE {          virtual void endSync() OVERRIDE {
322              const T clone = *data;              const T clone = SynchronizedConfig<T>::GetConfigForUpdate();
323              SynchronizedConfig<T>::SwitchConfig() = clone;              SynchronizedConfig<T>::SwitchConfig() = clone;
324              mutex.Unlock();              mutex.Unlock();
325          }          }
326    
327            const T& unsafeData() const {
328                return SynchronizedConfig<T>::GetUnsafeUpdateConfig();
329            }
330    
331      private:      private:
         T* data;  
332          Mutex mutex;          Mutex mutex;
333      };      };
334    
# Line 321  namespace LinuxSampler { Line 347  namespace LinuxSampler {
347      class FrontBuffer : public SynchronizedConfig<T>::Reader, public Synchronizer<T> {      class FrontBuffer : public SynchronizedConfig<T>::Reader, public Synchronizer<T> {
348      public:      public:
349          FrontBuffer(BackBuffer<T>& backBuffer) : SynchronizedConfig<T>::Reader::Reader(&backBuffer) {}          FrontBuffer(BackBuffer<T>& backBuffer) : SynchronizedConfig<T>::Reader::Reader(&backBuffer) {}
350          virtual T& beginSync() OVERRIDE { return SynchronizedConfig<T>::Reader::Lock(); }          virtual void beginSync() OVERRIDE { data = &SynchronizedConfig<T>::Reader::Lock(); }
351            virtual T& syncedData() OVERRIDE { return *data; }
352          virtual void endSync() OVERRIDE { SynchronizedConfig<T>::Reader::Unlock(); }          virtual void endSync() OVERRIDE { SynchronizedConfig<T>::Reader::Unlock(); }
353        private:
354            T* data;
355      };      };
356    
357      /**      /**
# Line 364  namespace LinuxSampler { Line 393  namespace LinuxSampler {
393          inline          inline
394          Sync<T> back() { return Sync<T>(&m_back); }          Sync<T> back() { return Sync<T>(&m_back); }
395    
396            /**
397             * Get the backbuffer data <b>unprotected</b>, that is <b>without</b>
398             * locking or any means of synchronizations.
399             *
400             * Due to its nature this must only be called for read access and
401             * you have to make sure by yourself, that the data/member you
402             * access is really safe for concurrent read access (i.e. SGI's
403             * implementation of std::vector::size() would be safe).
404             *
405             * Only use this when you are absolutely sure what you are doing!
406             */
407            const T& unsafeBack() const { return m_back.unsafeData(); }
408    
409      private:      private:
410          BackBuffer<T> m_back; ///< Back buffer (non real-time thread(s) side).          BackBuffer<T> m_back; ///< Back buffer (non real-time thread(s) side).
411          FrontBuffer<T> m_front; ///< Front buffer (real-time thread side).          FrontBuffer<T> m_front; ///< Front buffer (real-time thread side).

Legend:
Removed from v.2499  
changed lines
  Added in v.2500

  ViewVC Help
Powered by ViewVC