timer_pool.h revision 9cfff1a3bd75f9b78aaf2a8c3277ca97c12fa95c
1/* 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 17#ifndef CHRE_CORE_TIMER_POOL_H_ 18#define CHRE_CORE_TIMER_POOL_H_ 19 20#include "chre_api/chre/re.h" 21 22#include "chre/platform/mutex.h" 23#include "chre/platform/system_timer.h" 24#include "chre/util/non_copyable.h" 25#include "chre/util/priority_queue.h" 26 27namespace chre { 28 29/** 30 * The type to use when referring to a timer instance. 31 * 32 * Note that this mirrors the CHRE API definition of a timer handle, so should 33 * not be changed without appropriate consideration. 34 */ 35typedef uint32_t TimerHandle; 36 37//! Forward declare the EventLoop class to avoid a circular dependency between 38//! TimerPool and EventLoop. 39class EventLoop; 40 41/** 42 * Tracks requests from CHRE apps for timed events. 43 */ 44class TimerPool : public NonCopyable { 45 public: 46 /** 47 * Sets up the timer instance initial conditions. 48 * 49 * @param The event loop that owns this timer. 50 */ 51 TimerPool(EventLoop& eventLoop); 52 53 /** 54 * Requests a timer for a nanoapp given a cookie to pass to the nanoapp when 55 * the timer event is published. 56 * 57 * @param nanoapp The nanoapp for which this timer is being requested. 58 * @param duration The duration of the timer. 59 * @param cookie A cookie to pass to the app when the timer elapses. 60 * @param oneShot false if the timer is expected to auto-reload. 61 */ 62 TimerHandle setTimer(const Nanoapp *nanoapp, Nanoseconds duration, 63 const void *cookie, bool oneShot); 64 65 /** 66 * Cancels a timer given a handle. If the timer handle is invalid or the timer 67 * is not owned by the passed in nanoapp, false is returned. 68 * 69 * @param nanoapp The nanoapp requesting a timer to be cancelled. 70 * @param timerHandle The handle for a timer to be cancelled. 71 * @return true if the timer was cancelled successfully. 72 */ 73 bool cancelTimer(const Nanoapp* nanoapp, TimerHandle timerHandle); 74 75 // TODO: should also add methods here to: 76 // - post an event after a delay 77 // - invoke a callback in "unsafe" context (i.e. from other thread), which the 78 // CHRE system could use to trigger things while the task runner is busy 79 80 private: 81 /** 82 * Tracks metadata associated with a request for a timed event. 83 */ 84 struct TimerRequest { 85 //! The nanoapp instance ID from which this request was made. 86 uint32_t nanoappInstanceId; 87 88 //! The TimerHandle assigned to this request. 89 TimerHandle timerHandle; 90 91 //! The time when the request was made. 92 Nanoseconds expirationTime; 93 94 //! The requested duration of the timer. 95 Nanoseconds duration; 96 97 //! Whether or not the request is a one shot or should be rescheduled. 98 bool isOneShot; 99 100 //! The cookie pointer to be passed as an event to the requesting nanoapp. 101 const void *cookie; 102 103 /** 104 * Provides a greater than comparison of TimerRequests. 105 * 106 * @param request The other request to compare against. 107 * @return Returns true if this request is greater than the provided 108 * request. 109 */ 110 bool operator>(const TimerRequest& request) const; 111 }; 112 113 //! The mutex used to lock the shared data structures below. The 114 //! handleSystemTimerCallback may be called from any context so we use a lock 115 //! to ensure exclusive access. 116 // 117 // Consider changing the design here to avoid the use of a mutex. There is 118 // another option to post an event to the system task to re-schedule the next 119 // timer. It would simplify the design and make it easier to make future 120 // extensions to this module. 121 Mutex mMutex; 122 123 //! The event loop that owns this timer pool. 124 EventLoop& mEventLoop; 125 126 //! The queue of outstanding timer requests. 127 PriorityQueue<TimerRequest, std::greater<TimerRequest>> mTimerRequests; 128 129 //! The underlying system timer used to schedule delayed callbacks. 130 SystemTimer mSystemTimer; 131 132 //! The next timer handle for generateTimerHandle() to return. 133 TimerHandle mLastTimerHandle = CHRE_TIMER_INVALID; 134 135 //! Whether or not the timer handle generation logic needs to perform a 136 //! search for a vacant timer handle. 137 bool mGenerateTimerHandleMustCheckUniqueness = false; 138 139 /** 140 * Looks up a timer request given a timer handle. The lock must be acquired 141 * prior to entering this function. 142 * 143 * @param timerHandle The timer handle referring to a given request. 144 * @param index A pointer to the index of the handle. If the handle is found 145 * this will be populated with the index of the request from the list 146 * of requests. This is optional and will only be populated if not 147 * nullptr. 148 * @return A pointer to a TimerRequest or nullptr if no match is found. 149 */ 150 TimerRequest *getTimerRequestByTimerHandle(TimerHandle timerHandle, 151 size_t *index = nullptr); 152 153 /** 154 * Obtains a unique timer handle to return to an app requesting a timer. 155 * 156 * @return The guaranteed unique timer handle. 157 */ 158 TimerHandle generateTimerHandle(); 159 160 /** 161 * Obtains a unique timer handle by searching through the list of timer 162 * requests. This is a fallback for once the timer handles have been 163 * exhausted. The lock must be acquired prior to entering this function. 164 * 165 * @return A guaranteed unique timer handle. 166 */ 167 TimerHandle generateUniqueTimerHandle(); 168 169 /** 170 * Inserts a TimerRequest into the list of active timer requests. The order of 171 * mTimerRequests is always maintained such that the timer request with the 172 * closest expiration time is at the front of the list. 173 * 174 * @param timerRequest The timer request being inserted into the list. 175 */ 176 void insertTimerRequest(const TimerRequest& timerRequest); 177 178 /** 179 * Handles a completion callback for a timer by scheduling the next timer if 180 * available. If any timers have expired already an event is posted for them 181 * as well. 182 */ 183 void onSystemTimerCallback(); 184 185 /** 186 * Sets the underlying system timer to the next timer in the timer list if 187 * available. The lock must be acquired prior to entering this function. 188 * 189 * @return true if any timer events were posted 190 */ 191 bool handleExpiredTimersAndScheduleNext(); 192 193 /** 194 * This static method handles the callback from the system timer. The data 195 * pointer here is the TimerPool instance. 196 * 197 * @param data A pointer to the timer pool. 198 */ 199 static void handleSystemTimerCallback(void *timerPoolPtr); 200}; 201 202} // namespace chre 203 204#endif // CHRE_CORE_TIMER_POOL_H_ 205