diff options
author | David Robillard <d@drobilla.net> | 2008-08-19 18:33:12 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-08-19 18:33:12 +0000 |
commit | 680188cc2a73f5f907215efed6a68f7f21c60ea4 (patch) | |
tree | a8c71bc831f862a8254036f5d0a15aed79e43684 | |
parent | d9d81d15397c8ad1d503777025008489a60760c9 (diff) | |
download | raul-680188cc2a73f5f907215efed6a68f7f21c60ea4.tar.gz raul-680188cc2a73f5f907215efed6a68f7f21c60ea4.tar.bz2 raul-680188cc2a73f5f907215efed6a68f7f21c60ea4.zip |
More thread-safe ringbuffer.
Add test for size/full/empty queue functions.
git-svn-id: http://svn.drobilla.net/lad/raul@1446 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | raul/SRSWQueue.hpp | 30 | ||||
-rw-r--r-- | tests/queue_test.cpp | 27 |
2 files changed, 42 insertions, 15 deletions
diff --git a/raul/SRSWQueue.hpp b/raul/SRSWQueue.hpp index 0273f80..ad615e0 100644 --- a/raul/SRSWQueue.hpp +++ b/raul/SRSWQueue.hpp @@ -60,19 +60,19 @@ public: inline void pop(); private: - volatile size_t _front; ///< Index to front of queue (circular) - volatile size_t _back; ///< Index to back of queue (one past last element) (circular) - const size_t _size; ///< Size of @ref _objects (you can store _size-1 objects) - T* const _objects; ///< Fixed array containing queued elements + AtomicInt _front; ///< Index to front of queue (circular) + AtomicInt _back; ///< Index to back of queue (one past last element) (circular) + const size_t _size; ///< Size of @ref _objects (you can store _size-1 objects) + T* const _objects; ///< Fixed array containing queued elements }; template<typename T> SRSWQueue<T>::SRSWQueue(size_t size) -: _front(0), - _back(0), - _size(size+1), - _objects((T*)calloc(_size, sizeof(T))) + : _front(0) + , _back(0) + , _size(size+1) + , _objects((T*)calloc(_size, sizeof(T))) { assert(size > 1); } @@ -91,7 +91,7 @@ template <typename T> inline bool SRSWQueue<T>::empty() const { - return (_back == _front); + return (_back.get() == _front.get()); } @@ -101,8 +101,7 @@ template <typename T> inline bool SRSWQueue<T>::full() const { - // FIXME: uses both _front and _back - thread safe? - return ( ((_front - _back + _size) % _size) == 1 ); + return (((_front.get() - _back.get() + _size) % _size) == 1); } @@ -112,7 +111,7 @@ template <typename T> inline T& SRSWQueue<T>::front() const { - return _objects[_front]; + return _objects[_front.get()]; } @@ -128,8 +127,9 @@ SRSWQueue<T>::push(const T& elem) if (full()) { return false; } else { - _objects[_back] = elem; - _back = (_back + 1) % (_size); + unsigned back = _back.get(); + _objects[back] = elem; + _back = (back + 1) % _size; return true; } } @@ -148,7 +148,7 @@ SRSWQueue<T>::pop() assert(!empty()); assert(_size > 0); - _front = (_front + 1) % (_size); + _front = (_front.get() + 1) % (_size); } diff --git a/tests/queue_test.cpp b/tests/queue_test.cpp index 7a1d44b..1e92104 100644 --- a/tests/queue_test.cpp +++ b/tests/queue_test.cpp @@ -120,6 +120,33 @@ int main() { unsigned long total_processed = 0; + cout << "Testing size" << endl; + for (unsigned i=0; i < queue.capacity(); ++i) { + queue.push(i); + if (i == queue.capacity()-1) { + if (!queue.full()) { + cerr << "ERROR: Should be full at " << i + << " (size " << queue.capacity() << ")" << endl; + return -1; + } + } else { + if (queue.full()) { + cerr << "ERROR: Prematurely full at " << i + << " (size " << queue.capacity() << ")" << endl; + return -1; + } + } + } + + for (unsigned i=0; i < queue.capacity(); ++i) + queue.pop(); + + if (!queue.empty()) { + cerr << "ERROR: Should be empty" << endl; + return -1; + } + + cout << "Testing concurrent reading/writing" << endl; vector<WriteThread*> writers(NUM_WRITERS, new WriteThread()); struct termios orig_term; |