From ae9f2970367b252fd0a285c0126cfbe1affd10ba Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 16 Dec 2017 09:27:57 +0100 Subject: Use modern C++ atomics --- src/Queue.hpp | 61 ++++++++++++++++++----------------------------------------- 1 file changed, 18 insertions(+), 43 deletions(-) diff --git a/src/Queue.hpp b/src/Queue.hpp index 136de17..ab47aed 100644 --- a/src/Queue.hpp +++ b/src/Queue.hpp @@ -1,46 +1,36 @@ /* This file is part of Patchage. - * Copyright 2007-2014 David Robillard + * Copyright 2007-2017 David Robillard * * Patchage 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 3 of the License, or (at your option) - * any later version. + * Software Foundation, either version 3 of the License, or any later version. * * Patchage is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. * - * You should have received a copy of the GNU General Public License - * along with Patchage. If not, see . + * You should have received a copy of the GNU General Public License along with + * Patchage. If not, see . */ #ifndef QUEUE_HPP_INCLUDED #define QUEUE_HPP_INCLUDED +#include #include -#ifdef __APPLE__ -# include -#endif - -/** - Realtime-safe single-reader single-writer queue. - - This is a RingBuffer but templated for fixed sized objects which makes its - use a bit more efficient and cleaner in C++ than a traditional byte oriented - ring buffer. -*/ +/** Realtime-safe single-reader single-writer queue */ template class Queue { public: /** @param size Size in number of elements */ - explicit Queue(uint32_t size); + explicit Queue(size_t size); ~Queue(); // Any thread: - inline uint32_t capacity() const { return _size - 1; } + inline size_t capacity() const { return _size - 1; } // Write thread(s): @@ -54,27 +44,14 @@ public: inline void pop(); private: - Queue(const Queue&); ///< Undefined (noncopyable) - Queue& operator=(const Queue&); ///< Undefined (noncopyable) - - static inline void barrier() { -#if defined(__APPLE__) - OSMemoryBarrier(); -#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) - __sync_synchronize(); -#else -# warning Memory barriers unsupported, possible bugs on SMP systems -#endif - } - - int _front; ///< Index to front of queue - int _back; ///< Index to back of queue (1 past last element) - const uint32_t _size; ///< Size of _objects (1 more than can be stored) - T* const _objects; ///< Circular array containing queued elements + std::atomic _front; ///< Index to front of queue + std::atomic _back; ///< Index to back of queue (one past end) + const size_t _size; ///< Size of `_objects` (at most _size-1) + T* const _objects; ///< Fixed array containing queued elements }; template -Queue::Queue(uint32_t size) +Queue::Queue(size_t size) : _front(0) , _back(0) , _size(size + 1) @@ -95,7 +72,7 @@ template inline bool Queue::empty() const { - return (_back == _front); + return (_back.load() == _front.load()); } /** Return whether or not the queue is full. @@ -104,7 +81,7 @@ template inline bool Queue::full() const { - return (((_front - _back + _size) % _size) == 1); + return (((_front.load() - _back.load() + _size) % _size) == 1); } /** Return the element at the front of the queue without removing it @@ -113,7 +90,7 @@ template inline T& Queue::front() const { - return _objects[_front]; + return _objects[_front.load()]; } /** Push an item onto the back of the Queue - realtime-safe, not thread-safe. @@ -128,9 +105,8 @@ Queue::push(const T& elem) if (full()) { return false; } else { - const int back = _back; + unsigned back = _back.load(); _objects[back] = elem; - barrier(); _back = (back + 1) % _size; return true; } @@ -149,8 +125,7 @@ Queue::pop() assert(!empty()); assert(_size > 0); - barrier(); - _front = (_front + 1) % (_size); + _front = (_front.load() + 1) % (_size); } #endif // QUEUE_HPP_INCLUDED -- cgit v1.2.1