blob: b1d8ed4e36d6730cc28ce45398ab8cff12d3b8a8 [file] [log] [blame]
Anil Admald3bef872019-07-30 17:59:58 -07001/*
2 * Copyright (C) 2019 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_hardware_gnss_common_vts_GnssCallbackEventQueue_H_
18#define android_hardware_gnss_common_vts_GnssCallbackEventQueue_H_
19
20#include <log/log.h>
21
22#include <condition_variable>
23#include <deque>
24#include <list>
25#include <mutex>
26
27namespace android {
28namespace hardware {
29namespace gnss {
30namespace common {
31
32/*
33 * Producer/consumer queue for storing/retrieving callback events from GNSS HAL.
34 */
35template <class T>
36class GnssCallbackEventQueue {
37 public:
38 GnssCallbackEventQueue(const std::string& name) : name_(name), called_count_(0){};
39 ~GnssCallbackEventQueue() { reset(); }
40
41 /* Adds callback event to the end of the queue. */
42 void store(const T& event);
43
44 /*
45 * Removes the callack event at the front of the queue, stores it in event parameter
46 * and returns true. Returns false on timeout and event is not populated.
47 */
48 bool retrieve(T& event, int timeout_seconds);
49
50 /*
51 * Removes parameter count number of callack events at the front of the queue, stores
52 * them in event_list parameter and returns the number of events retrieved. Waits up to
53 * timeout_seconds to retrieve each event. If timeout occurs, it returns the number of
54 * items retrieved which will be less than count.
55 */
56 int retrieve(list<T>& event_list, int count, int timeout_seconds);
57
58 /* Returns the number of events pending to be retrieved from the callback event queue. */
59 int size() const;
60
61 /* Returns the number of callback events received since last reset(). */
62 int calledCount() const;
63
64 /* Clears the callback event queue and resets the calledCount() to 0. */
65 void reset();
66
67 private:
68 GnssCallbackEventQueue(const GnssCallbackEventQueue&) = delete;
69 GnssCallbackEventQueue& operator=(const GnssCallbackEventQueue&) = delete;
70
71 std::string name_;
72 int called_count_;
73 mutable std::recursive_mutex mtx_;
74 std::condition_variable_any cv_;
75 std::deque<T> events_;
76};
77
78template <class T>
79void GnssCallbackEventQueue<T>::store(const T& event) {
80 std::unique_lock<std::recursive_mutex> lock(mtx_);
81 events_.push_back(event);
82 ++called_count_;
83 lock.unlock();
84 cv_.notify_all();
85}
86
87template <class T>
88bool GnssCallbackEventQueue<T>::retrieve(T& event, int timeout_seconds) {
89 std::unique_lock<std::recursive_mutex> lock(mtx_);
90 cv_.wait_for(lock, std::chrono::seconds(timeout_seconds), [&] { return !events_.empty(); });
91 if (events_.empty()) {
92 return false;
93 }
94 event = events_.front();
95 events_.pop_front();
96 return true;
97}
98
99template <class T>
100int GnssCallbackEventQueue<T>::retrieve(list<T>& event_list, int count, int timeout_seconds) {
101 for (int i = 0; i < count; ++i) {
102 T event;
103 if (!retrieve(event, timeout_seconds)) {
104 return i;
105 }
106 event_list.push_back(event);
107 }
108
109 return count;
110}
111
112template <class T>
113int GnssCallbackEventQueue<T>::size() const {
114 std::unique_lock<std::recursive_mutex> lock(mtx_);
115 return events_.size();
116}
117
118template <class T>
119int GnssCallbackEventQueue<T>::calledCount() const {
120 std::unique_lock<std::recursive_mutex> lock(mtx_);
121 return called_count_;
122}
123
124template <class T>
125void GnssCallbackEventQueue<T>::reset() {
126 std::unique_lock<std::recursive_mutex> lock(mtx_);
127 if (!events_.empty()) {
128 ALOGW("%u unprocessed events discarded in callback queue %s", (unsigned int)events_.size(),
129 name_.c_str());
130 }
131 events_.clear();
132 called_count_ = 0;
133}
134
135} // namespace common
136} // namespace gnss
137} // namespace hardware
138} // namespace android
139
140#endif // android_hardware_gnss_common_vts_GnssCallbackEventQueue_H_