array_queue.h revision e64f180233e64c40b56993cfea3696c5b4b16395
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef CHRE_UTIL_ARRAY_QUEUE_H_ 18#define CHRE_UTIL_ARRAY_QUEUE_H_ 19 20#include <type_traits> 21 22namespace chre { 23 24// TODO: this code is not done, just left for now as a reference 25 26/* 27 * TODO: need to implement thread-safe fifo queue that doesn't use dynamic 28 * memory... we can have something like this: 29 * - array of data types 30 * - head/tail index for data 31 * - head for free list (only needs to be singly-linked) 32 * - note that free list will use same array as linkage for active elements 33 * 34 * Don't worry about this for now, just use STL. 35 * 36 * This file is a WIP and probably doesn't work... 37 */ 38 39 40// TODO: create a thread-safe wrapper for this, e.g. LockedArrayQueue. Starting 41// with single-threaded implementation for now 42 43template<typename ElementType, uint16_t kSize> 44class ArrayQueue { 45 public: 46 ArrayQueue() { 47 for (size_t i = 0; i < kSize - 1; i++) { 48 mNext[i] = i + 1; 49 } 50 mNext[kSize - 1] = kInvalidItem; 51 mHead = kInvalidItem; 52 mTail = kInvalidItem; 53 mFreeHead = 0; 54 } 55 56 // TODO: assert that T is trivially move/copy constructable? 57 58 static_assert(kSize < UINT16_MAX, 59 "ArrayList only supports up to UINT16_MAX-1 elements"); 60 typedef std::conditional<(kSize >= UINT8_MAX), uint16_t, uint8_t>::type 61 IndexType; 62 constexpr IndexType kInvalidItem = (sizeof(IndexType) == sizeof(uint8_t)) ? 63 UINT8_MAX : UINT16_MAX; 64 65 bool pushBack(const ElementType &data) { 66 if (mFreeHead != kInvalidItem) { 67 mData[mFreeHead] = data; 68 mNext[mTail] = mFreeHead; 69 mTail = mFreeHead; 70 if (mHead == kInvalidItem) { 71 mHead = mTail; 72 } 73 mFreeHead = mNext[mFreeHead]; 74 return true; 75 } else { 76 // todo: no space... 77 LOGE("Tried to push to full queue"); 78 return false; 79 } 80 } 81 82 // todo: this queue needs to be single consumer, so we know that front() 83 // will not get freed while we're using it. maybe we add extra debug on here 84 // too like ASSERT(getThreadId() == mLastPopThreadId)... 85 86 bool empty() const { 87 return (mHead == kInvalidItem); 88 } 89 90 ElementType &front() { 91 ASSERT(mHead < kSize); 92 return mData[mHead]; 93 } 94 95 const ElementType &front() const { 96 ASSERT(mHead < kSize); 97 return mData[mHead]; 98 } 99 100 // general usage semantics 101 // while (!q.empty()) { T x = q.front(); x.doSomething(); q.popFront(); } 102 103 // Unlinks the front item from the list, and marks its storage as available 104 // for pushing new items to the queue. 105 void popFront() { 106 if (mHead != kInvalidItem) { 107 mData[mHead].~ElementType(); 108 LinkType newHead = mNext[mHead]; 109 mNext[mHead] = mFreeHead; 110 mFreeHead = mHead; 111 mHead = newHead; 112 if (mHead == kInvalidItem) { 113 mTail = kInvalidItem; 114 } 115 } else { 116 LOGE("Tried to pop empty list"); 117 } 118 } 119 120 private: 121 ElementType mData[kSize]; 122 123 // Contains the index for the "next" element in the queue, or kInvalidItem 124 // if there is no next item. Note that this array contains two 125 // non-overlapping lists, one that identifies which indices in mData are 126 // free (starting from mFreeHead), and another for the active part of the 127 // list (mHead and mTail). 128 IndexType mNext[kSize]; 129 IndexType mHead; 130 IndexType mTail; 131 IndexType mFreeHead; 132 133 // TODO: lock 134}; 135 136} // namespace chre 137 138#endif // CHRE_UTIL_ARRAY_QUEUE_H_ 139