/* ZynAddSubFX - a software synthesizer SafeQueue.cpp - Yet Another Lockless Ringbuffer Copyright (C) 2016 Mark McCurry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ namespace zyncarla { template SafeQueue::SafeQueue(size_t maxlen) :writePtr(0), readPtr(0), bufSize(maxlen) { w_space.init(PTHREAD_PROCESS_PRIVATE, maxlen - 1); r_space.init(PTHREAD_PROCESS_PRIVATE, 0); buffer = new T[maxlen]; } template SafeQueue::~SafeQueue() { delete [] buffer; } template unsigned int SafeQueue::size() const { return rSpace(); } template unsigned int SafeQueue::rSpace() const { return r_space.getvalue(); } template unsigned int SafeQueue::wSpace() const { return w_space.getvalue(); } template int SafeQueue::push(const T &in) { if(!wSpace()) return -1; //ok, there is space to write size_t w = (writePtr + 1) % bufSize; buffer[w] = in; writePtr = w; //adjust ranges w_space.wait(); //guaranteed not to wait r_space.post(); return 0; } template int SafeQueue::peak(T &out) const { if(!rSpace()) return -1; //ok, there is space to read size_t r = (readPtr + 1) % bufSize; out = buffer[r]; return 0; } template int SafeQueue::pop(T &out) { if(!rSpace()) return -1; //ok, there is space to read size_t r = (readPtr + 1) % bufSize; out = buffer[r]; readPtr = r; //adjust ranges r_space.wait(); //guaranteed not to wait w_space.post(); return 0; } template void SafeQueue::clear() { //thread unsafe while(!r_space.trywait()) w_space.post(); readPtr = writePtr; } }