zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

SafeQueue.cpp (1960B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   SafeQueue.cpp - Yet Another Lockless Ringbuffer
      5   Copyright (C) 2016 Mark McCurry
      6 
      7   This program is free software; you can redistribute it and/or
      8   modify it under the terms of the GNU General Public License
      9   as published by the Free Software Foundation; either version 2
     10   of the License, or (at your option) any later version.
     11 */
     12 
     13 namespace zyn {
     14 
     15 template<class T>
     16 SafeQueue<T>::SafeQueue(size_t maxlen)
     17     :writePtr(0), readPtr(0), bufSize(maxlen)
     18 {
     19     w_space.init(PTHREAD_PROCESS_PRIVATE, maxlen - 1);
     20     r_space.init(PTHREAD_PROCESS_PRIVATE, 0);
     21     buffer = new T[maxlen];
     22 }
     23 
     24 template<class T>
     25 SafeQueue<T>::~SafeQueue()
     26 {
     27     delete [] buffer;
     28 }
     29 
     30 template<class T>
     31 unsigned int SafeQueue<T>::size() const
     32 {
     33     return rSpace();
     34 }
     35 
     36 template<class T>
     37 unsigned int SafeQueue<T>::rSpace() const
     38 {
     39     return r_space.getvalue();
     40 }
     41 
     42 template<class T>
     43 unsigned int SafeQueue<T>::wSpace() const
     44 {
     45     return w_space.getvalue();
     46 }
     47 
     48 template<class T>
     49 int SafeQueue<T>::push(const T &in)
     50 {
     51     if(!wSpace())
     52         return -1;
     53 
     54     //ok, there is space to write
     55     size_t w = (writePtr + 1) % bufSize;
     56     buffer[w] = in;
     57     writePtr  = w;
     58 
     59     //adjust ranges
     60     w_space.wait(); //guaranteed not to wait
     61     r_space.post();
     62     return 0;
     63 }
     64 
     65 template<class T>
     66 int SafeQueue<T>::peak(T &out) const
     67 {
     68     if(!rSpace())
     69         return -1;
     70 
     71     //ok, there is space to read
     72     size_t r = (readPtr + 1) % bufSize;
     73     out     = buffer[r];
     74 
     75     return 0;
     76 }
     77 
     78 template<class T>
     79 int SafeQueue<T>::pop(T &out)
     80 {
     81     if(!rSpace())
     82         return -1;
     83 
     84     //ok, there is space to read
     85     size_t r = (readPtr + 1) % bufSize;
     86     out     = buffer[r];
     87     readPtr = r;
     88 
     89     //adjust ranges
     90     r_space.wait(); //guaranteed not to wait
     91     w_space.post();
     92     return 0;
     93 }
     94 
     95 template<class T>
     96 void SafeQueue<T>::clear()
     97 {
     98     //thread unsafe
     99     while(!r_space.trywait())
    100         w_space.post();
    101     readPtr = writePtr;
    102 }
    103 
    104 }