blob: 80123ba3267d3506ccd0cb51baf2b1d1f59f418e [file] [log] [blame]
Yifan Hongb93f0502016-10-28 10:42:57 -07001/*
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
Yifan Hong5e2318c2016-10-27 17:19:21 -070017#ifndef ANDROID_SYNCHRONIZED_QUEUE_H
18#define ANDROID_SYNCHRONIZED_QUEUE_H
19
Steven Moreland7e3a2a22016-09-15 09:04:37 -070020#include <condition_variable>
21#include <mutex>
22#include <queue>
23#include <thread>
24
Yifan Hong5e2318c2016-10-27 17:19:21 -070025namespace android {
26namespace hardware {
Steven Moreland7e3a2a22016-09-15 09:04:37 -070027/* Threadsafe queue.
28 */
29template <typename T>
30struct SynchronizedQueue {
31
32 /* Gets an item from the front of the queue.
33 *
34 * Blocks until the item is available.
35 */
36 T wait_pop();
37
38 /* Puts an item onto the end of the queue.
39 */
Yifan Hong5e2318c2016-10-27 17:19:21 -070040 bool push(const T& item);
Steven Moreland7e3a2a22016-09-15 09:04:37 -070041
42 /* Gets the size of the array.
43 */
44 size_t size();
45
Yifan Hong5e2318c2016-10-27 17:19:21 -070046 /* Sets the limit to the queue. Will fail
47 * the push operation if the limit is reached.
48 */
49 void setLimit(size_t limit);
50
Steven Moreland7e3a2a22016-09-15 09:04:37 -070051private:
52 std::condition_variable mCondition;
53 std::mutex mMutex;
54 std::queue<T> mQueue;
Yifan Hong5e2318c2016-10-27 17:19:21 -070055 size_t mQueueLimit = SIZE_MAX;
Steven Moreland7e3a2a22016-09-15 09:04:37 -070056};
57
58template <typename T>
59T SynchronizedQueue<T>::wait_pop() {
60 std::unique_lock<std::mutex> lock(mMutex);
61
62 mCondition.wait(lock, [this]{
63 return !this->mQueue.empty();
64 });
65
66 T item = mQueue.front();
67 mQueue.pop();
68
69 return item;
70}
71
72template <typename T>
Yifan Hong5e2318c2016-10-27 17:19:21 -070073bool SynchronizedQueue<T>::push(const T &item) {
74 bool success;
Steven Moreland7e3a2a22016-09-15 09:04:37 -070075 {
76 std::unique_lock<std::mutex> lock(mMutex);
Yifan Hong5e2318c2016-10-27 17:19:21 -070077 if (mQueue.size() < mQueueLimit) {
78 mQueue.push(item);
79 success = true;
80 } else {
81 success = false;
82 }
Steven Moreland7e3a2a22016-09-15 09:04:37 -070083 }
84
85 mCondition.notify_one();
Yifan Hong5e2318c2016-10-27 17:19:21 -070086 return success;
Steven Moreland7e3a2a22016-09-15 09:04:37 -070087}
88
89template <typename T>
90size_t SynchronizedQueue<T>::size() {
91 std::unique_lock<std::mutex> lock(mMutex);
92
93 return mQueue.size();
Yifan Hongb93f0502016-10-28 10:42:57 -070094}
Yifan Hong5e2318c2016-10-27 17:19:21 -070095
96template <typename T>
97void SynchronizedQueue<T>::setLimit(size_t limit) {
98 std::unique_lock<std::mutex> lock(mMutex);
99
100 mQueueLimit = limit;
101}
102
103} // namespace hardware
104} // namespace android
105
106#endif