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 ANDROID_HIDL_SYNCHRONIZED_QUEUE_H 18 #define ANDROID_HIDL_SYNCHRONIZED_QUEUE_H 19 20 #include <condition_variable> 21 #include <mutex> 22 #include <queue> 23 #include <thread> 24 25 namespace android { 26 namespace hardware { 27 namespace details { 28 /* Threadsafe queue. 29 */ 30 template <typename T> 31 struct SynchronizedQueue { 32 SynchronizedQueue(size_t limit); 33 34 /* Gets an item from the front of the queue. 35 * 36 * Blocks until the item is available. 37 */ 38 T wait_pop(); 39 40 /* Puts an item onto the end of the queue. 41 */ 42 bool push(const T& item); 43 44 /* Gets the size of the array. 45 */ 46 size_t size(); 47 lockSynchronizedQueue48 std::unique_lock<std::mutex> lock() { 49 return std::unique_lock<std::mutex>(mMutex); 50 } 51 isInitializedLockedSynchronizedQueue52 bool isInitializedLocked() { 53 return mInitialized; 54 } setInitializedLockedSynchronizedQueue55 void setInitializedLocked(bool isInitialized) { 56 mInitialized = isInitialized; 57 } 58 59 private: 60 std::condition_variable mCondition; 61 std::mutex mMutex; 62 std::queue<T> mQueue; 63 const size_t mQueueLimit; 64 bool mInitialized = false; 65 }; 66 67 template <typename T> SynchronizedQueue(size_t limit)68SynchronizedQueue<T>::SynchronizedQueue(size_t limit) : mQueueLimit(limit) { 69 } 70 71 template <typename T> wait_pop()72T SynchronizedQueue<T>::wait_pop() { 73 std::unique_lock<std::mutex> lock(mMutex); 74 75 mCondition.wait(lock, [this]{ 76 return !this->mQueue.empty(); 77 }); 78 79 T item = mQueue.front(); 80 mQueue.pop(); 81 82 return item; 83 } 84 85 template <typename T> push(const T & item)86bool SynchronizedQueue<T>::push(const T &item) { 87 bool success; 88 { 89 std::unique_lock<std::mutex> lock(mMutex); 90 if (mQueue.size() < mQueueLimit) { 91 mQueue.push(item); 92 success = true; 93 } else { 94 success = false; 95 } 96 } 97 98 mCondition.notify_one(); 99 return success; 100 } 101 102 template <typename T> size()103size_t SynchronizedQueue<T>::size() { 104 std::unique_lock<std::mutex> lock(mMutex); 105 106 return mQueue.size(); 107 } 108 109 } // namespace details 110 } // namespace hardware 111 } // namespace android 112 113 #endif // ANDROID_HIDL_SYNCHRONIZED_QUEUE_H 114