aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/samples/RhythmGame/src/main/cpp/utils/LockFreeQueue.h
diff options
context:
space:
mode:
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.h154
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