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 
48 private:
49     std::condition_variable mCondition;
50     std::mutex mMutex;
51     std::queue<T> mQueue;
52     const size_t mQueueLimit;
53 };
54 
55 template <typename T>
SynchronizedQueue(size_t limit)56 SynchronizedQueue<T>::SynchronizedQueue(size_t limit) : mQueueLimit(limit) {
57 }
58 
59 template <typename T>
wait_pop()60 T SynchronizedQueue<T>::wait_pop() {
61     std::unique_lock<std::mutex> lock(mMutex);
62 
63     mCondition.wait(lock, [this]{
64         return !this->mQueue.empty();
65     });
66 
67     T item = mQueue.front();
68     mQueue.pop();
69 
70     return item;
71 }
72 
73 template <typename T>
push(const T & item)74 bool SynchronizedQueue<T>::push(const T &item) {
75     bool success;
76     {
77         std::unique_lock<std::mutex> lock(mMutex);
78         if (mQueue.size() < mQueueLimit) {
79             mQueue.push(item);
80             success = true;
81         } else {
82             success = false;
83         }
84     }
85 
86     mCondition.notify_one();
87     return success;
88 }
89 
90 template <typename T>
size()91 size_t SynchronizedQueue<T>::size() {
92     std::unique_lock<std::mutex> lock(mMutex);
93 
94     return mQueue.size();
95 }
96 
97 } // namespace details
98 } // namespace hardware
99 } // namespace android
100 
101 #endif // ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
102