1 /*
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
27 namespace android {
28 namespace hardware {
29 namespace gnss {
30 namespace common {
31
32 /*
33 * Producer/consumer queue for storing/retrieving callback events from GNSS HAL.
34 */
35 template <class T>
36 class GnssCallbackEventQueue {
37 public:
GnssCallbackEventQueue(const std::string & name)38 GnssCallbackEventQueue(const std::string& name) : name_(name), called_count_(0){};
~GnssCallbackEventQueue()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(std::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
78 template <class T>
store(const T & event)79 void 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
87 template <class T>
retrieve(T & event,int timeout_seconds)88 bool 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
99 template <class T>
retrieve(std::list<T> & event_list,int count,int timeout_seconds)100 int GnssCallbackEventQueue<T>::retrieve(std::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
112 template <class T>
size()113 int GnssCallbackEventQueue<T>::size() const {
114 std::unique_lock<std::recursive_mutex> lock(mtx_);
115 return events_.size();
116 }
117
118 template <class T>
calledCount()119 int GnssCallbackEventQueue<T>::calledCount() const {
120 std::unique_lock<std::recursive_mutex> lock(mtx_);
121 return called_count_;
122 }
123
124 template <class T>
reset()125 void 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_
141