diff options
author | David Robillard <d@drobilla.net> | 2017-12-16 09:27:57 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2017-12-16 09:27:57 +0100 |
commit | ae9f2970367b252fd0a285c0126cfbe1affd10ba (patch) | |
tree | 466a396780bcc7cc0729568b57c8cae1dcc28046 /src/Queue.hpp | |
parent | 3b18ee6cd6778136180062c0e4cf69e2635da966 (diff) | |
download | patchage-ae9f2970367b252fd0a285c0126cfbe1affd10ba.tar.gz patchage-ae9f2970367b252fd0a285c0126cfbe1affd10ba.tar.bz2 patchage-ae9f2970367b252fd0a285c0126cfbe1affd10ba.zip |
Use modern C++ atomics
Diffstat (limited to 'src/Queue.hpp')
-rw-r--r-- | src/Queue.hpp | 61 |
1 files 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 <http://drobilla.net> + * Copyright 2007-2017 David Robillard <http://drobilla.net> * * 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 <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU General Public License along with + * Patchage. If not, see <http://www.gnu.org/licenses/>. */ #ifndef QUEUE_HPP_INCLUDED #define QUEUE_HPP_INCLUDED +#include <atomic> #include <cassert> -#ifdef __APPLE__ -# include <libkern/OSAtomic.h> -#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 <typename T> 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<size_t> _front; ///< Index to front of queue + std::atomic<size_t> _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<typename T> -Queue<T>::Queue(uint32_t size) +Queue<T>::Queue(size_t size) : _front(0) , _back(0) , _size(size + 1) @@ -95,7 +72,7 @@ template <typename T> inline bool Queue<T>::empty() const { - return (_back == _front); + return (_back.load() == _front.load()); } /** Return whether or not the queue is full. @@ -104,7 +81,7 @@ template <typename T> inline bool Queue<T>::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 <typename T> inline T& Queue<T>::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<T>::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<T>::pop() assert(!empty()); assert(_size > 0); - barrier(); - _front = (_front + 1) % (_size); + _front = (_front.load() + 1) % (_size); } #endif // QUEUE_HPP_INCLUDED |