event_loop.h revision 09a4783208b5ba1e14d0f0102eb31e688caca28d
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_EVENT_LOOP_H_ 18#define CHRE_CORE_EVENT_LOOP_H_ 19 20#include "chre/core/event.h" 21#include "chre/core/nanoapp.h" 22#include "chre/core/timer_pool.h" 23#include "chre/platform/mutex.h" 24#include "chre/platform/platform_nanoapp.h" 25#include "chre/util/dynamic_vector.h" 26#include "chre/util/fixed_size_blocking_queue.h" 27#include "chre/util/non_copyable.h" 28#include "chre/util/synchronized_memory_pool.h" 29#include "chre/util/unique_ptr.h" 30 31namespace chre { 32 33/** 34 * The EventLoop represents a single thread of execution that is shared among 35 * zero or more nanoapps. As the name implies, the EventLoop is built around a 36 * loop that delivers events to the nanoapps managed within for processing. 37 */ 38class EventLoop : public NonCopyable { 39 public: 40 /** 41 * Setup the event loop. 42 */ 43 EventLoop(); 44 45 /** 46 * Synchronous callback used with forEachNanoapp 47 */ 48 typedef void (NanoappCallbackFunction)(const Nanoapp *nanoapp, void *data); 49 50 /** 51 * Searches the set of nanoapps managed by this EventLoop for one with the 52 * given app ID. If found, provides its instance ID, which can be used to send 53 * events to the app. 54 * 55 * This function is safe to call from any thread. 56 * 57 * @param appId The nanoapp identifier to search for. 58 * @param instanceId If this function returns true, will be populated with the 59 * instanceId associated with the given appId; otherwise unmodified. 60 * Must not be null. 61 * @return true if the given app ID was found and instanceId was populated 62 */ 63 bool findNanoappInstanceIdByAppId(uint64_t appId, uint32_t *instanceId); 64 65 /** 66 * Iterates over the list of Nanoapps managed by this EventLoop, and invokes 67 * the supplied callback for each one. This holds a lock if necessary, so it 68 * is safe to call from any thread. 69 * 70 * @param callback Function to invoke on each Nanoapp (synchronously) 71 * @param data Arbitrary data to pass to the callback 72 */ 73 void forEachNanoapp(NanoappCallbackFunction *callback, void *data); 74 75 /** 76 * Invokes a message to host free callback supplied by the given nanoapp 77 * (identified by app ID). Ensures that the calling context is updated 78 * appropriately. 79 * 80 * @param appId Identifies the nanoapp that sent this message and supplied the 81 * free callback 82 * @param freeFunction The non-null message free callback given by the nanoapp 83 * @param message Pointer to the message data 84 * @param messageSize Size of the message 85 */ 86 void invokeMessageFreeFunction( 87 uint64_t appId, chreMessageFreeFunction *freeFunction, void *message, 88 size_t messageSize); 89 90 /** 91 * Invokes the Nanoapp's start callback, and if successful, adds it to the 92 * set of Nanoapps managed by this EventLoop. This function must only be 93 * called from the context of the thread that runs this event loop (i.e. from 94 * the same thread that will call run() or from a callback invoked within 95 * run()). 96 * 97 * @param nanoapp The nanoapp that will be started. Upon success, this 98 * UniquePtr will become invalid, as the underlying Nanoapp instance 99 * will have been transferred to be managed by this EventLoop. 100 * @return true if the app was started successfully 101 */ 102 bool startNanoapp(UniquePtr<Nanoapp>& nanoapp); 103 104 /** 105 * Stops a nanoapp by invoking the stop entry point. The nanoapp passed in 106 * must have been previously started by the startNanoapp method. After this 107 * function returns, all references to the Nanoapp are invalid. 108 * 109 * @param nanoapp A pointer to the nanoapp to stop. 110 */ 111 void stopNanoapp(Nanoapp *nanoapp); 112 113 /** 114 * Executes the loop that blocks on the event queue and delivers received 115 * events to nanoapps. Only returns after stop() is called (from another 116 * context). 117 */ 118 void run(); 119 120 /** 121 * Signals the event loop currently executing in run() to exit gracefully at 122 * the next available opportunity. This function is thread-safe. 123 */ 124 void stop(); 125 126 /** 127 * Posts an event to a nanoapp that is currently running (or all nanoapps if 128 * the target instance ID is kBroadcastInstanceId). 129 * 130 * This function is safe to call from any thread. 131 * 132 * @param eventType The type of data being posted. 133 * @param eventData The data being posted. 134 * @param freeCallback The callback to invoke when the event is no longer 135 * needed. 136 * @param senderInstanceId The instance ID of the sender of this event. 137 * @param targetInstanceId The instance ID of the destination of this event. 138 * 139 * @return true if the event was successfully added to the queue. Note that 140 * unlike chreSendEvent, this does *not* invoke the free callback if 141 * it failed to post the event. 142 * 143 * @see chreSendEvent 144 */ 145 bool postEvent(uint16_t eventType, void *eventData, 146 chreEventCompleteFunction *freeCallback, 147 uint32_t senderInstanceId = kSystemInstanceId, 148 uint32_t targetInstanceId = kBroadcastInstanceId); 149 150 /** 151 * Returns a pointer to the currently executing Nanoapp, or nullptr if none is 152 * currently executing. Must only be called from within the thread context 153 * associated with this EventLoop. 154 * 155 * @return the currently executing nanoapp, or nullptr 156 */ 157 Nanoapp *getCurrentNanoapp() const; 158 159 /** 160 * Gets the number of nanoapps currently associated with this event loop. Must 161 * only be called within the context of this EventLoop. 162 * 163 * @return The number of nanoapps managed by this event loop 164 */ 165 size_t getNanoappCount() const; 166 167 /** 168 * Obtains the TimerPool associated with this event loop. 169 * 170 * @return The timer pool owned by this event loop. 171 */ 172 TimerPool& getTimerPool(); 173 174 /** 175 * Searches the set of nanoapps managed by this EventLoop for one with the 176 * given instance ID. 177 * 178 * This function is safe to call from any thread. 179 * 180 * @param instanceId The nanoapp instance ID to search for. 181 * @return a pointer to the found nanoapp or nullptr if no match was found. 182 */ 183 Nanoapp *findNanoappByInstanceId(uint32_t instanceId); 184 185 private: 186 //! The maximum number of events that can be active in the system. 187 static constexpr size_t kMaxEventCount = 1024; 188 189 //! The maximum number of events that are awaiting to be scheduled. These 190 //! events are in a queue to be distributed to apps. 191 static constexpr size_t kMaxUnscheduledEventCount = 1024; 192 193 //! The memory pool to allocate incoming events from. 194 SynchronizedMemoryPool<Event, kMaxEventCount> mEventPool; 195 196 //! The timer used schedule timed events for tasks running in this event loop. 197 TimerPool mTimerPool; 198 199 //! The list of nanoapps managed by this event loop. 200 DynamicVector<UniquePtr<Nanoapp>> mNanoapps; 201 202 //! This lock *must* be held whenever we: 203 //! (1) make changes to the mNanoapps vector, or 204 //! (2) read the mNanoapps vector from a thread other than the one 205 //! associated with this EventLoop 206 //! It is not necessary to acquire the lock when reading mNanoapps from within 207 //! the thread context of this EventLoop. 208 Mutex mNanoappsLock; 209 210 //! The blocking queue of incoming events from the system that have not been 211 //! distributed out to apps yet. 212 FixedSizeBlockingQueue<Event *, kMaxUnscheduledEventCount> mEvents; 213 214 // TODO: should probably be atomic to be fully correct 215 volatile bool mRunning = true; 216 217 Nanoapp *mCurrentApp = nullptr; 218 219 /** 220 * Delivers the next event pending in the Nanoapp's queue, and takes care of 221 * freeing events once they have been delivered to all nanoapps. Must only be 222 * called after confirming that the app has at least 1 pending event. 223 * 224 * @return true if the nanoapp has another event pending in its queue 225 */ 226 bool deliverNextEvent(const UniquePtr<Nanoapp>& app); 227 228 /** 229 * Call after when an Event has been delivered to all intended recipients. 230 * Invokes the event's free callback (if given) and releases resources. 231 * 232 * @param event The event to be freed 233 */ 234 void freeEvent(Event *event); 235 236 /** 237 * Finds a Nanoapp with the given 64-bit appId. 238 * 239 * Only safe to call within this EventLoop's thread. 240 * 241 * @param appId Nanoapp ID 242 * @return Pointer to Nanoapp instance in this EventLoop with the given app 243 * ID, or nullptr if not found 244 */ 245 Nanoapp *lookupAppByAppId(uint64_t appId); 246 247 /** 248 * Finds a Nanoapp with the given instanceId. 249 * 250 * Only safe to call within this EventLoop's thread. 251 * 252 * @param instanceId Nanoapp instance identifier 253 * @return Nanoapp with the given instanceId, or nullptr if not found 254 */ 255 Nanoapp *lookupAppByInstanceId(uint32_t instanceId); 256 257 /** 258 * Stops the Nanoapp at the given index in mNanoapps 259 */ 260 void stopNanoapp(size_t index); 261}; 262 263} // namespace chre 264 265#endif // CHRE_CORE_EVENT_LOOP_H_ 266