xref: /aosp_15_r20/system/libhidl/base/SynchronizedQueue.h (revision 8222fbe171c3d6fadfe95119c180cf3010c392a8)
1*8222fbe1SAndroid Build Coastguard Worker /*
2*8222fbe1SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*8222fbe1SAndroid Build Coastguard Worker  *
4*8222fbe1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8222fbe1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8222fbe1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8222fbe1SAndroid Build Coastguard Worker  *
8*8222fbe1SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8222fbe1SAndroid Build Coastguard Worker  *
10*8222fbe1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8222fbe1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8222fbe1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8222fbe1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8222fbe1SAndroid Build Coastguard Worker  * limitations under the License.
15*8222fbe1SAndroid Build Coastguard Worker  */
16*8222fbe1SAndroid Build Coastguard Worker 
17*8222fbe1SAndroid Build Coastguard Worker #ifndef ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
18*8222fbe1SAndroid Build Coastguard Worker #define ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
19*8222fbe1SAndroid Build Coastguard Worker 
20*8222fbe1SAndroid Build Coastguard Worker #include <condition_variable>
21*8222fbe1SAndroid Build Coastguard Worker #include <mutex>
22*8222fbe1SAndroid Build Coastguard Worker #include <queue>
23*8222fbe1SAndroid Build Coastguard Worker #include <thread>
24*8222fbe1SAndroid Build Coastguard Worker 
25*8222fbe1SAndroid Build Coastguard Worker namespace android {
26*8222fbe1SAndroid Build Coastguard Worker namespace hardware {
27*8222fbe1SAndroid Build Coastguard Worker namespace details {
28*8222fbe1SAndroid Build Coastguard Worker /* Threadsafe queue.
29*8222fbe1SAndroid Build Coastguard Worker  */
30*8222fbe1SAndroid Build Coastguard Worker template <typename T>
31*8222fbe1SAndroid Build Coastguard Worker struct SynchronizedQueue {
32*8222fbe1SAndroid Build Coastguard Worker     SynchronizedQueue(size_t limit);
33*8222fbe1SAndroid Build Coastguard Worker 
34*8222fbe1SAndroid Build Coastguard Worker     /* Gets an item from the front of the queue.
35*8222fbe1SAndroid Build Coastguard Worker      *
36*8222fbe1SAndroid Build Coastguard Worker      * Blocks until the item is available.
37*8222fbe1SAndroid Build Coastguard Worker      */
38*8222fbe1SAndroid Build Coastguard Worker     T wait_pop();
39*8222fbe1SAndroid Build Coastguard Worker 
40*8222fbe1SAndroid Build Coastguard Worker     /* Puts an item onto the end of the queue.
41*8222fbe1SAndroid Build Coastguard Worker      */
42*8222fbe1SAndroid Build Coastguard Worker     bool push(const T& item);
43*8222fbe1SAndroid Build Coastguard Worker 
44*8222fbe1SAndroid Build Coastguard Worker     /* Gets the size of the array.
45*8222fbe1SAndroid Build Coastguard Worker      */
46*8222fbe1SAndroid Build Coastguard Worker     size_t size();
47*8222fbe1SAndroid Build Coastguard Worker 
lockSynchronizedQueue48*8222fbe1SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> lock() {
49*8222fbe1SAndroid Build Coastguard Worker         return std::unique_lock<std::mutex>(mMutex);
50*8222fbe1SAndroid Build Coastguard Worker     }
51*8222fbe1SAndroid Build Coastguard Worker 
isInitializedLockedSynchronizedQueue52*8222fbe1SAndroid Build Coastguard Worker     bool isInitializedLocked() {
53*8222fbe1SAndroid Build Coastguard Worker         return mInitialized;
54*8222fbe1SAndroid Build Coastguard Worker     }
setInitializedLockedSynchronizedQueue55*8222fbe1SAndroid Build Coastguard Worker     void setInitializedLocked(bool isInitialized) {
56*8222fbe1SAndroid Build Coastguard Worker         mInitialized = isInitialized;
57*8222fbe1SAndroid Build Coastguard Worker     }
58*8222fbe1SAndroid Build Coastguard Worker 
59*8222fbe1SAndroid Build Coastguard Worker private:
60*8222fbe1SAndroid Build Coastguard Worker     std::condition_variable mCondition;
61*8222fbe1SAndroid Build Coastguard Worker     std::mutex mMutex;
62*8222fbe1SAndroid Build Coastguard Worker     std::queue<T> mQueue;
63*8222fbe1SAndroid Build Coastguard Worker     const size_t mQueueLimit;
64*8222fbe1SAndroid Build Coastguard Worker     bool mInitialized = false;
65*8222fbe1SAndroid Build Coastguard Worker };
66*8222fbe1SAndroid Build Coastguard Worker 
67*8222fbe1SAndroid Build Coastguard Worker template <typename T>
SynchronizedQueue(size_t limit)68*8222fbe1SAndroid Build Coastguard Worker SynchronizedQueue<T>::SynchronizedQueue(size_t limit) : mQueueLimit(limit) {
69*8222fbe1SAndroid Build Coastguard Worker }
70*8222fbe1SAndroid Build Coastguard Worker 
71*8222fbe1SAndroid Build Coastguard Worker template <typename T>
wait_pop()72*8222fbe1SAndroid Build Coastguard Worker T SynchronizedQueue<T>::wait_pop() {
73*8222fbe1SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> lock(mMutex);
74*8222fbe1SAndroid Build Coastguard Worker 
75*8222fbe1SAndroid Build Coastguard Worker     mCondition.wait(lock, [this]{
76*8222fbe1SAndroid Build Coastguard Worker         return !this->mQueue.empty();
77*8222fbe1SAndroid Build Coastguard Worker     });
78*8222fbe1SAndroid Build Coastguard Worker 
79*8222fbe1SAndroid Build Coastguard Worker     T item = mQueue.front();
80*8222fbe1SAndroid Build Coastguard Worker     mQueue.pop();
81*8222fbe1SAndroid Build Coastguard Worker 
82*8222fbe1SAndroid Build Coastguard Worker     return item;
83*8222fbe1SAndroid Build Coastguard Worker }
84*8222fbe1SAndroid Build Coastguard Worker 
85*8222fbe1SAndroid Build Coastguard Worker template <typename T>
push(const T & item)86*8222fbe1SAndroid Build Coastguard Worker bool SynchronizedQueue<T>::push(const T &item) {
87*8222fbe1SAndroid Build Coastguard Worker     bool success;
88*8222fbe1SAndroid Build Coastguard Worker     {
89*8222fbe1SAndroid Build Coastguard Worker         std::unique_lock<std::mutex> lock(mMutex);
90*8222fbe1SAndroid Build Coastguard Worker         if (mQueue.size() < mQueueLimit) {
91*8222fbe1SAndroid Build Coastguard Worker             mQueue.push(item);
92*8222fbe1SAndroid Build Coastguard Worker             success = true;
93*8222fbe1SAndroid Build Coastguard Worker         } else {
94*8222fbe1SAndroid Build Coastguard Worker             success = false;
95*8222fbe1SAndroid Build Coastguard Worker         }
96*8222fbe1SAndroid Build Coastguard Worker     }
97*8222fbe1SAndroid Build Coastguard Worker 
98*8222fbe1SAndroid Build Coastguard Worker     mCondition.notify_one();
99*8222fbe1SAndroid Build Coastguard Worker     return success;
100*8222fbe1SAndroid Build Coastguard Worker }
101*8222fbe1SAndroid Build Coastguard Worker 
102*8222fbe1SAndroid Build Coastguard Worker template <typename T>
size()103*8222fbe1SAndroid Build Coastguard Worker size_t SynchronizedQueue<T>::size() {
104*8222fbe1SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> lock(mMutex);
105*8222fbe1SAndroid Build Coastguard Worker 
106*8222fbe1SAndroid Build Coastguard Worker     return mQueue.size();
107*8222fbe1SAndroid Build Coastguard Worker }
108*8222fbe1SAndroid Build Coastguard Worker 
109*8222fbe1SAndroid Build Coastguard Worker } // namespace details
110*8222fbe1SAndroid Build Coastguard Worker } // namespace hardware
111*8222fbe1SAndroid Build Coastguard Worker } // namespace android
112*8222fbe1SAndroid Build Coastguard Worker 
113*8222fbe1SAndroid Build Coastguard Worker #endif // ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
114