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

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

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

revision 1789 by senoner, Wed Nov 14 15:06:48 2007 UTC revision 1790 by persson, Sun Nov 2 12:05:00 2008 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005, 2006 Christian Schoenebeck                        *   *   Copyright (C) 2005 - 2008 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   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 28  Line 28 
28    
29  #include <string.h>  #include <string.h>
30    
31  #include "atomic.h"  #include "lsatomic.h"
32    
33    using LinuxSampler::atomic;
34    using LinuxSampler::memory_order_relaxed;
35    using LinuxSampler::memory_order_acquire;
36    using LinuxSampler::memory_order_release;
37    
38    
39  /** @brief Real-time safe and type safe RingBuffer implementation.  /** @brief Real-time safe and type safe RingBuffer implementation.
40   *   *
# Line 61  template<class T, bool T_DEEP_COPY> Line 67  template<class T, bool T_DEEP_COPY>
67  class RingBuffer  class RingBuffer
68  {  {
69  public:  public:
70      RingBuffer (int sz, int wrap_elements = DEFAULT_WRAP_ELEMENTS) {      RingBuffer (int sz, int wrap_elements = DEFAULT_WRAP_ELEMENTS) :
71            write_ptr(0), read_ptr(0) {
72              int power_of_two;              int power_of_two;
73    
74              this->wrap_elements = wrap_elements;              this->wrap_elements = wrap_elements;
# Line 73  public: Line 80  public:
80              size = 1<<power_of_two;              size = 1<<power_of_two;
81              size_mask = size;              size_mask = size;
82              size_mask -= 1;              size_mask -= 1;
             atomic_set(&write_ptr, 0);  
             atomic_set(&read_ptr, 0);  
83              buf = new T[size + wrap_elements];              buf = new T[size + wrap_elements];
84      };      };
85    
# Line 92  public: Line 97  public:
97       * any additional data on the heap by itself.       * any additional data on the heap by itself.
98       */       */
99      inline void fill_write_space_with_null() {      inline void fill_write_space_with_null() {
100               int w = atomic_read(&write_ptr),               int w = write_ptr.load(memory_order_relaxed),
101                   r = atomic_read(&read_ptr);                   r = read_ptr.load(memory_order_acquire);
102               memset(get_write_ptr(), 0, sizeof(T)*write_space_to_end());               memset(get_write_ptr(), 0, sizeof(T)*write_space_to_end());
103               if (r && w >= r) {               if (r && w >= r) {
104                 memset(get_buffer_begin(), 0, sizeof(T)*(r - 1));                 memset(get_buffer_begin(), 0, sizeof(T)*(r - 1));
# Line 112  public: Line 117  public:
117      __inline T *get_buffer_begin();      __inline T *get_buffer_begin();
118    
119      __inline T *get_read_ptr(void) {      __inline T *get_read_ptr(void) {
120        return(&buf[atomic_read(&read_ptr)]);        return(&buf[read_ptr.load(memory_order_relaxed)]);
121      }      }
122    
123      /**      /**
# Line 120  public: Line 125  public:
125       * advanced by \a offset elements.       * advanced by \a offset elements.
126       */       */
127      /*inline T* get_read_ptr(int offset) {      /*inline T* get_read_ptr(int offset) {
128          int r = atomic_read(&read_ptr);          int r = read_ptr.load(memory_order_relaxed);
129          r += offset;          r += offset;
130          r &= size_mask;          r &= size_mask;
131          return &buf[r];          return &buf[r];
# Line 128  public: Line 133  public:
133    
134      __inline T *get_write_ptr();      __inline T *get_write_ptr();
135      __inline void increment_read_ptr(int cnt) {      __inline void increment_read_ptr(int cnt) {
136                 atomic_set(&read_ptr , (atomic_read(&read_ptr) + cnt) & size_mask);                 read_ptr.store((read_ptr.load(memory_order_relaxed) + cnt) & size_mask, memory_order_release);
137               }               }
138      __inline void set_read_ptr(int val) {      __inline void set_read_ptr(int val) {
139                 atomic_set(&read_ptr , val);                 read_ptr.store(val, memory_order_release);
140               }               }
141    
142      __inline void increment_write_ptr(int cnt) {      __inline void increment_write_ptr(int cnt) {
143                 atomic_set(&write_ptr,  (atomic_read(&write_ptr) + cnt) & size_mask);                 write_ptr.store((write_ptr.load(memory_order_relaxed) + cnt) & size_mask, memory_order_release);
144               }               }
145    
146      /* this function increments the write_ptr by cnt, if the buffer wraps then      /* this function increments the write_ptr by cnt, if the buffer wraps then
# Line 150  public: Line 155  public:
155         and the write ptr incremented accordingly.         and the write ptr incremented accordingly.
156      */      */
157      __inline void increment_write_ptr_with_wrap(int cnt) {      __inline void increment_write_ptr_with_wrap(int cnt) {
158                 int w=atomic_read(&write_ptr);                 int w = write_ptr.load(memory_order_relaxed);
159                 w += cnt;                 w += cnt;
160                 if(w >= size) {                 if(w >= size) {
161                   w -= size;                   w -= size;
162                   copy(&buf[0], &buf[size], w);                   copy(&buf[0], &buf[size], w);
163  //printf("DEBUG !!!! increment_write_ptr_with_wrap: buffer wrapped, elements wrapped = %d (wrap_elements %d)\n",w,wrap_elements);  //printf("DEBUG !!!! increment_write_ptr_with_wrap: buffer wrapped, elements wrapped = %d (wrap_elements %d)\n",w,wrap_elements);
164                 }                 }
165                 atomic_set(&write_ptr, w);                 write_ptr.store(w, memory_order_release);
166               }               }
167    
168      /* this function returns the available write space in the buffer      /* this function returns the available write space in the buffer
# Line 177  public: Line 182  public:
182      __inline int write_space_to_end_with_wrap() {      __inline int write_space_to_end_with_wrap() {
183                int w, r;                int w, r;
184    
185                w = atomic_read(&write_ptr);                w = write_ptr.load(memory_order_relaxed);
186                r = atomic_read(&read_ptr);                r = read_ptr.load(memory_order_acquire);
187  //printf("write_space_to_end: w=%d r=%d\n",w,r);  //printf("write_space_to_end: w=%d r=%d\n",w,r);
188                if(r > w) {                if(r > w) {
189                  //printf("DEBUG: write_space_to_end_with_wrap: r>w r=%d w=%d val=%d\n",r,w,r - w - 1);                  //printf("DEBUG: write_space_to_end_with_wrap: r>w r=%d w=%d val=%d\n",r,w,r - w - 1);
# Line 216  public: Line 221  public:
221             */             */
222      __inline int adjust_write_space_to_avoid_boundary(int cnt, int capped_cnt) {      __inline int adjust_write_space_to_avoid_boundary(int cnt, int capped_cnt) {
223                 int w;                 int w;
224                 w = atomic_read(&write_ptr);                 w = write_ptr.load(memory_order_relaxed);
225                 if((w+capped_cnt) >= size && (w+capped_cnt) < (size+wrap_elements)) {                 if((w+capped_cnt) >= size && (w+capped_cnt) < (size+wrap_elements)) {
226  //printf("adjust_write_space_to_avoid_boundary returning cnt = %d\n",cnt);  //printf("adjust_write_space_to_avoid_boundary returning cnt = %d\n",cnt);
227                   return(cnt);                   return(cnt);
# Line 228  public: Line 233  public:
233      __inline int write_space_to_end() {      __inline int write_space_to_end() {
234                int w, r;                int w, r;
235    
236                w = atomic_read(&write_ptr);                w = write_ptr.load(memory_order_relaxed);
237                r = atomic_read(&read_ptr);                r = read_ptr.load(memory_order_acquire);
238  //printf("write_space_to_end: w=%d r=%d\n",w,r);  //printf("write_space_to_end: w=%d r=%d\n",w,r);
239                if(r > w) return(r - w - 1);                if(r > w) return(r - w - 1);
240                if(r) return(size - w);                if(r) return(size - w);
# Line 239  public: Line 244  public:
244      __inline int read_space_to_end() {      __inline int read_space_to_end() {
245                int w, r;                int w, r;
246    
247                w = atomic_read(&write_ptr);                w = write_ptr.load(memory_order_acquire);
248                r = atomic_read(&read_ptr);                r = read_ptr.load(memory_order_relaxed);
249                if(w >= r) return(w - r);                if(w >= r) return(w - r);
250                return(size - r);                return(size - r);
251              }              }
252      __inline void init() {      __inline void init() {
253                     atomic_set(&write_ptr, 0);                     write_ptr.store(0, memory_order_relaxed);
254                     atomic_set(&read_ptr, 0);                     read_ptr.store(0, memory_order_relaxed);
255                   //  wrap=0;                   //  wrap=0;
256              }              }
257    
258      int write_space () {      int write_space () {
259              int w, r;              int w, r;
260    
261              w = atomic_read(&write_ptr);              w = write_ptr.load(memory_order_relaxed);
262              r = atomic_read(&read_ptr);              r = read_ptr.load(memory_order_acquire);
263    
264              if (w > r) {              if (w > r) {
265                      return ((r - w + size) & size_mask) - 1;                      return ((r - w + size) & size_mask) - 1;
# Line 268  public: Line 273  public:
273      int read_space () {      int read_space () {
274              int w, r;              int w, r;
275    
276              w = atomic_read(&write_ptr);              w = write_ptr.load(memory_order_acquire);
277              r = atomic_read(&read_ptr);              r = read_ptr.load(memory_order_relaxed);
278    
279              if (w >= r) {              if (w >= r) {
280                      return w - r;                      return w - r;
# Line 291  public: Line 296  public:
296          public:          public:
297              int read_space() {              int read_space() {
298                  int r = read_ptr;                  int r = read_ptr;
299                  int w = atomic_read(&pBuf->write_ptr);                  int w = pBuf->write_ptr.load(memory_order_acquire);
300                  return (w >= r) ? w - r : (w - r + pBuf->size) & pBuf->size_mask;                  return (w >= r) ? w - r : (w - r + pBuf->size) & pBuf->size_mask;
301              }              }
302    
# Line 300  public: Line 305  public:
305               * read position by one.               * read position by one.
306               */               */
307              inline void operator--() {              inline void operator--() {
308                  if (read_ptr == atomic_read(&pBuf->read_ptr)) return; //TODO: or should we react oh this case (e.g. force segfault), as this is a very odd case?                  if (read_ptr == pBuf->read_ptr.load(memory_order_relaxed)) return; //TODO: or should we react oh this case (e.g. force segfault), as this is a very odd case?
309                  read_ptr = (read_ptr-1) & pBuf->size_mask;                  read_ptr = (read_ptr-1) & pBuf->size_mask;
310              }              }
311    
# Line 391  public: Line 396  public:
396               * @see RingBuffer::increment_read_ptr()               * @see RingBuffer::increment_read_ptr()
397               */               */
398              void free() {              void free() {
399                  atomic_set(&pBuf->read_ptr, read_ptr);                  pBuf->read_ptr.store(read_ptr, memory_order_release);
400              }              }
401    
402          protected:          protected:
403              _NonVolatileReader(RingBuffer<T1,T1_DEEP_COPY>* pBuf) {              _NonVolatileReader(RingBuffer<T1,T1_DEEP_COPY>* pBuf) {
404                  this->pBuf     = pBuf;                  this->pBuf     = pBuf;
405                  this->read_ptr = atomic_read(&pBuf->read_ptr);                  this->read_ptr = pBuf->read_ptr.load(memory_order_relaxed);
406              }              }
407    
408              RingBuffer<T1,T1_DEEP_COPY>* pBuf;              RingBuffer<T1,T1_DEEP_COPY>* pBuf;
# Line 412  public: Line 417  public:
417    
418    protected:    protected:
419      T *buf;      T *buf;
420      atomic_t write_ptr;      atomic<int> write_ptr;
421      atomic_t read_ptr;      atomic<int> read_ptr;
422      int size_mask;      int size_mask;
423    
424      /**      /**
# Line 427  public: Line 432  public:
432    
433  template<class T, bool T_DEEP_COPY>  template<class T, bool T_DEEP_COPY>
434  T* RingBuffer<T,T_DEEP_COPY>::get_write_ptr (void) {  T* RingBuffer<T,T_DEEP_COPY>::get_write_ptr (void) {
435    return(&buf[atomic_read(&write_ptr)]);    return(&buf[write_ptr.load(memory_order_relaxed)]);
436  }  }
437    
438  template<class T, bool T_DEEP_COPY>  template<class T, bool T_DEEP_COPY>
# Line 446  int RingBuffer<T,T_DEEP_COPY>::read(T* d Line 451  int RingBuffer<T,T_DEEP_COPY>::read(T* d
451          int n1, n2;          int n1, n2;
452          int priv_read_ptr;          int priv_read_ptr;
453    
454          priv_read_ptr=atomic_read(&read_ptr);          priv_read_ptr = read_ptr.load(memory_order_relaxed);
455    
456          if ((free_cnt = read_space ()) == 0) {          if ((free_cnt = read_space ()) == 0) {
457                  return 0;                  return 0;
# Line 472  int RingBuffer<T,T_DEEP_COPY>::read(T* d Line 477  int RingBuffer<T,T_DEEP_COPY>::read(T* d
477                  priv_read_ptr = n2;                  priv_read_ptr = n2;
478          }          }
479    
480          atomic_set(&read_ptr, priv_read_ptr);          read_ptr.store(priv_read_ptr, memory_order_release);
481          return to_read;          return to_read;
482  }  }
483    
# Line 485  int RingBuffer<T,T_DEEP_COPY>::write(T* Line 490  int RingBuffer<T,T_DEEP_COPY>::write(T*
490          int n1, n2;          int n1, n2;
491          int priv_write_ptr;          int priv_write_ptr;
492    
493          priv_write_ptr=atomic_read(&write_ptr);          priv_write_ptr = write_ptr.load(memory_order_relaxed);
494    
495          if ((free_cnt = write_space ()) == 0) {          if ((free_cnt = write_space ()) == 0) {
496                  return 0;                  return 0;
# Line 510  int RingBuffer<T,T_DEEP_COPY>::write(T* Line 515  int RingBuffer<T,T_DEEP_COPY>::write(T*
515                  copy(buf, src+n1, n2);                  copy(buf, src+n1, n2);
516                  priv_write_ptr = n2;                  priv_write_ptr = n2;
517          }          }
518          atomic_set(&write_ptr, priv_write_ptr);          write_ptr.store(priv_write_ptr, memory_order_release);
519          return to_write;          return to_write;
520  }  }
521    

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

  ViewVC Help
Powered by ViewVC