blob: 1813130d841c7f0f869f259e03d238bc5f38ce7c [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 Hong0a351392017-03-20 17:17:52 -070017#ifndef ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
18#define ANDROID_HIDL_SYNCHRONIZED_QUEUE_H
Yifan Hong5e2318c2016-10-27 17:19:21 -070019
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 {
Yifan Hong0a351392017-03-20 17:17:52 -070027namespace details {
Steven Moreland7e3a2a22016-09-15 09:04:37 -070028/* Threadsafe queue.
29 */
30template <typename T>
31struct SynchronizedQueue {
32
33 /* Gets an item from the front of the queue.
34 *
35 * Blocks until the item is available.
36 */
37 T wait_pop();
38
39 /* Puts an item onto the end of the queue.
40 */
Yifan Hong5e2318c2016-10-27 17:19:21 -070041 bool push(const T& item);
Steven Moreland7e3a2a22016-09-15 09:04:37 -070042
43 /* Gets the size of the array.
44 */
45 size_t size();
46
Yifan Hong5e2318c2016-10-27 17:19:21 -070047 /* Sets the limit to the queue. Will fail
48 * the push operation if the limit is reached.
49 */
50 void setLimit(size_t limit);
51
Steven Moreland7e3a2a22016-09-15 09:04:37 -070052private:
53 std::condition_variable mCondition;
54 std::mutex mMutex;
55 std::queue<T> mQueue;
Yifan Hong5e2318c2016-10-27 17:19:21 -070056 size_t mQueueLimit = SIZE_MAX;
Steven Moreland7e3a2a22016-09-15 09:04:37 -070057};
58
59template <typename T>
60T 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
73template <typename T>
Yifan Hong5e2318c2016-10-27 17:19:21 -070074bool SynchronizedQueue<T>::push(const T &item) {
75 bool success;
Steven Moreland7e3a2a22016-09-15 09:04:37 -070076 {
77 std::unique_lock<std::mutex> lock(mMutex);
Yifan Hong5e2318c2016-10-27 17:19:21 -070078 if (mQueue.size() < mQueueLimit) {
79 mQueue.push(item);
80 success = true;
81 } else {
82 success = false;
83 }
Steven Moreland7e3a2a22016-09-15 09:04:37 -070084 }
85
86 mCondition.notify_one();
Yifan Hong5e2318c2016-10-27 17:19:21 -070087 return success;
Steven Moreland7e3a2a22016-09-15 09:04:37 -070088}
89
90template <typename T>
91size_t SynchronizedQueue<T>::size() {
92 std::unique_lock<std::mutex> lock(mMutex);
93
94 return mQueue.size();
Yifan Hongb93f0502016-10-28 10:42:57 -070095}
Yifan Hong5e2318c2016-10-27 17:19:21 -070096
97template <typename T>
98void SynchronizedQueue<T>::setLimit(size_t limit) {
99 std::unique_lock<std::mutex> lock(mMutex);
100
101 mQueueLimit = limit;
102}
103
Yifan Hong0a351392017-03-20 17:17:52 -0700104} // namespace details
Yifan Hong5e2318c2016-10-27 17:19:21 -0700105} // namespace hardware
106} // namespace android
107
Yifan Hong0a351392017-03-20 17:17:52 -0700108#endif // ANDROID_HIDL_SYNCHRONIZED_QUEUE_H