diff options
Diffstat (limited to 'externals/oboe/samples/RhythmGame/src/main/cpp/utils/LockFreeQueue.h')
| -rw-r--r-- | externals/oboe/samples/RhythmGame/src/main/cpp/utils/LockFreeQueue.h | 154 |
1 files changed, 0 insertions, 154 deletions
diff --git a/externals/oboe/samples/RhythmGame/src/main/cpp/utils/LockFreeQueue.h b/externals/oboe/samples/RhythmGame/src/main/cpp/utils/LockFreeQueue.h deleted file mode 100644 index fa9f7168bb..0000000000 --- a/externals/oboe/samples/RhythmGame/src/main/cpp/utils/LockFreeQueue.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef RHYTHMGAME_LOCKFREEQUEUE_H -#define RHYTHMGAME_LOCKFREEQUEUE_H - -#include <cstdint> -#include <atomic> - -/** - * A lock-free queue for single consumer, single producer. Not thread-safe when using multiple - * consumers or producers. - * - * Example code: - * - * LockFreeQueue<int, 1024> myQueue; - * int value = 123; - * myQueue.push(value); - * myQueue.pop(value); - * - * @tparam T - The item type - * @tparam CAPACITY - Maximum number of items which can be held in the queue. Must be a power of 2. - * Must be less than the maximum value permissible in INDEX_TYPE - * @tparam INDEX_TYPE - The internal index type, defaults to uint32_t. Changing this will affect - * the maximum capacity. Included for ease of unit testing because testing queue lengths of - * UINT32_MAX can be time consuming and is not always possible. - */ - -template <typename T, uint32_t CAPACITY, typename INDEX_TYPE = uint32_t> -class LockFreeQueue { -public: - - /** - * Implementation details: - * - * We have 2 counters: readCounter and writeCounter. Each will increment until it reaches - * INDEX_TYPE_MAX, then wrap to zero. Unsigned integer overflow is defined behaviour in C++. - * - * Each time we need to access our data array we call mask() which gives us the index into the - * array. This approach avoids having a "dead item" in the buffer to distinguish between full - * and empty states. It also allows us to have a size() method which is easily calculated. - * - * IMPORTANT: This implementation is only thread-safe with a single reader thread and a single - * writer thread. Have more than one of either will result in Bad Thingsā¢. - */ - - static constexpr bool isPowerOfTwo(uint32_t n) { return (n & (n - 1)) == 0; } - static_assert(isPowerOfTwo(CAPACITY), "Capacity must be a power of 2"); - static_assert(std::is_unsigned<INDEX_TYPE>::value, "Index type must be unsigned"); - - /** - * Pop a value off the head of the queue - * - * @param val - element will be stored in this variable - * @return true if value was popped successfully, false if the queue is empty - */ - bool pop(T &val) { - if (isEmpty()){ - return false; - } else { - val = buffer[mask(readCounter)]; - ++readCounter; - return true; - } - } - - /** - * Add an item to the back of the queue - * - * @param item - The item to add - * @return true if item was added, false if the queue was full - */ - bool push(const T& item) { - if (isFull()){ - return false; - } else { - buffer[mask(writeCounter)] = item; - ++writeCounter; - return true; - } - } - - /** - * Get the item at the front of the queue but do not remove it - * - * @param item - item will be stored in this variable - * @return true if item was stored, false if the queue was empty - */ - bool peek(T &item) const { - if (isEmpty()){ - return false; - } else { - item = buffer[mask(readCounter)]; - return true; - } - } - - /** - * Get the number of items in the queue - * - * @return number of items in the queue - */ - INDEX_TYPE size() const { - - /** - * This is worth some explanation: - * - * Whilst writeCounter is greater than readCounter the result of (write - read) will always - * be positive. Simple. - * - * But when writeCounter is equal to INDEX_TYPE_MAX (e.g. UINT32_MAX) the next push will - * wrap it around to zero, the start of the buffer, making writeCounter less than - * readCounter so the result of (write - read) will be negative. - * - * But because we're returning an unsigned type return value will be as follows: - * - * returnValue = INDEX_TYPE_MAX - (write - read) - * - * e.g. if write is 0, read is 150 and the INDEX_TYPE is uint8_t where the max value is - * 255 the return value will be (255 - (0 - 150)) = 105. - * - */ - return writeCounter - readCounter; - }; - -private: - - bool isEmpty() const { return readCounter == writeCounter; } - - bool isFull() const { return size() == CAPACITY; } - - INDEX_TYPE mask(INDEX_TYPE n) const { return static_cast<INDEX_TYPE>(n & (CAPACITY - 1)); } - - T buffer[CAPACITY]; - std::atomic<INDEX_TYPE> writeCounter { 0 }; - std::atomic<INDEX_TYPE> readCounter { 0 }; - -}; - -#endif //RHYTHMGAME_LOCKFREEQUEUE_H |
