summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-08-19 18:33:12 +0000
committerDavid Robillard <d@drobilla.net>2008-08-19 18:33:12 +0000
commit680188cc2a73f5f907215efed6a68f7f21c60ea4 (patch)
treea8c71bc831f862a8254036f5d0a15aed79e43684
parentd9d81d15397c8ad1d503777025008489a60760c9 (diff)
downloadraul-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.hpp30
-rw-r--r--tests/queue_test.cpp27
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;