event_loop.h revision 2de17c9c5c541d72248f8371dfb4d7e402dc93e8
1e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie/* 2e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Copyright (C) 2016 The Android Open Source Project 3e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 4e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Licensed under the Apache License, Version 2.0 (the "License"); 5e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * you may not use this file except in compliance with the License. 6e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * You may obtain a copy of the License at 7e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 8e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * http://www.apache.org/licenses/LICENSE-2.0 9e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 10e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Unless required by applicable law or agreed to in writing, software 11e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * distributed under the License is distributed on an "AS IS" BASIS, 12e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * See the License for the specific language governing permissions and 14e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * limitations under the License. 15e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 16e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 17e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#ifndef CHRE_CORE_EVENT_LOOP_H_ 18e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#define CHRE_CORE_EVENT_LOOP_H_ 19e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 20e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/core/event.h" 21e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/core/nanoapp.h" 22fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol#include "chre/core/timer_pool.h" 23977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie#include "chre/platform/mutex.h" 242de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol#include "chre/platform/platform_nanoapp.h" 25c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol#include "chre/util/dynamic_vector.h" 26022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol#include "chre/util/fixed_size_blocking_queue.h" 27e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/util/non_copyable.h" 28a1d5686c7513f6b8a436efd9f554d8c2227a2291Brian Duddie#include "chre/util/synchronized_memory_pool.h" 292de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol#include "chre/util/unique_ptr.h" 30e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 31e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddienamespace chre { 32e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 33e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie/** 34977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * The EventLoop represents a single thread of execution that is shared among 35977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * zero or more nanoapps. As the name implies, the EventLoop is built around a 36977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * loop that delivers events to the nanoapps managed within for processing. 37e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 38e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddieclass EventLoop : public NonCopyable { 39e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie public: 40fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol /** 41fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol * Setup the event loop. 42fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol */ 43fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol EventLoop(); 44fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol 45977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie /** 46977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Searches the set of nanoapps managed by this EventLoop for one with the 47977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * given app ID. If found, provides its instance ID, which can be used to send 48977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * events to the app. 49977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * 50977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * This function is safe to call from any thread. 51977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * 52977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @param appId The nanoapp identifier to search for. 53977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @param instanceId If this function returns true, will be populated with the 54977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * instanceId associated with the given appId; otherwise unmodified. 55977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Must not be null. 56977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @return true if the given app ID was found and instanceId was populated 57977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie */ 58977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie bool findNanoappInstanceIdByAppId(uint64_t appId, uint32_t *instanceId); 59e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 60e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie /** 612de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol * Starts a nanoapp by constructing a Nanoapp instance, invoking the start 622de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol * entry point and adding it to the list of nanoapps owned by this event 632de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol * loop. 64e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 652de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol * @param platformNanoapp A pointer to the platform nanoapp to start. This 662de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol * pointer must remain valid after this function returns. 67e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * @return True if the app was started successfully. 68e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 692de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol bool startNanoapp(PlatformNanoapp *platformNanoapp); 70e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 71e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie /** 72e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Stops a nanoapp by invoking the stop entry point. The nanoapp passed in 73e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * must have been previously started by the startNanoapp method. 74e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 75e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * @param A pointer to the nanoapp to stop. 76e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 77e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie void stopNanoapp(Nanoapp *nanoapp); 78e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 79e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie /** 80977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Executes the loop that blocks on the event queue and delivers received 81977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * events to nanoapps. Only returns after stop() is called (from another 82977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * context). 83e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 84e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie void run(); 85e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 86e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie /** 87e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Signals the event loop currently executing in run() to exit gracefully at 88f80ea015d077330cfdbd619680b250915ffcf1d2Brian Duddie * the next available opportunity. This function is thread-safe. 89e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 90e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie void stop(); 91e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 924927ee586656424c827920876673228fbdcf27c3Andrew Rossignol /** 934927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * Posts an event to a nanoapp that is currently running (or all nanoapps if 94042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie * the target instance ID is kBroadcastInstanceId). 95042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie * 96042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie * This function is safe to call from any thread. 974927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * 984927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * @param The type of data being posted. 994927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * @param The data being posted. 1004927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * @param The callback to invoke when the event is no longer needed. 1014927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * @param The instance ID of the sender of this event. 1024927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * @param The instance ID of the destination of this event. 1034927ee586656424c827920876673228fbdcf27c3Andrew Rossignol * 104042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie * @return true if the event was successfully added to the queue 1054927ee586656424c827920876673228fbdcf27c3Andrew Rossignol */ 106042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie bool postEvent(uint16_t eventType, void *eventData, 1074927ee586656424c827920876673228fbdcf27c3Andrew Rossignol chreEventCompleteFunction *freeCallback, 1084927ee586656424c827920876673228fbdcf27c3Andrew Rossignol uint32_t senderInstanceId = kSystemInstanceId, 1094927ee586656424c827920876673228fbdcf27c3Andrew Rossignol uint32_t targetInstanceId = kBroadcastInstanceId); 110e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 111e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie /** 112e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Returns a pointer to the currently executing Nanoapp, or nullptr if none is 113977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * currently executing. Must only be called from within the thread context 114977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * associated with this EventLoop. 115e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 116977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @return the currently executing nanoapp, or nullptr 117e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 1187983050d7cd84f1d5736f220ef9fd49be716b2c8Andrew Rossignol Nanoapp *getCurrentNanoapp() const; 119e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 120e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie /** 121e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * Returns a guaranteed unique instance ID that can be used to construct a 122e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * nanoapp. 123e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * 124e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie * @return a unique instance ID to assign to a nanoapp. 125e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */ 126977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie // TODO: move this to EventLoopManager as it must be unique across all event 127977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie // loops; we currently really only support one EventLoop so it's OK for now 128e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie uint32_t getNextInstanceId(); 129e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 130725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol /** 131725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol * Obtains the TimerPool associated with this event loop. 132725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol * 133725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol * @return The timer pool owned by this event loop. 134725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol */ 135725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol TimerPool& getTimerPool(); 136725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol 13730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol /** 13830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * Searches the set of nanoapps managed by this EventLoop for one with the 13930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * given instance ID. 14030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * 14130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * This function is safe to call from any thread. 14230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * 14330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * @param instanceId The nanoapp instance ID to search for. 14430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol * @return a pointer to the found nanoapp or nullptr if no match was found. 14530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol */ 14630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol Nanoapp *findNanoappByInstanceId(uint32_t instanceId); 14730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol 148e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie private: 1494927ee586656424c827920876673228fbdcf27c3Andrew Rossignol //! The maximum number of events that can be active in the system. 1504927ee586656424c827920876673228fbdcf27c3Andrew Rossignol static constexpr size_t kMaxEventCount = 1024; 1514927ee586656424c827920876673228fbdcf27c3Andrew Rossignol 152022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol //! The maximum number of events that are awaiting to be scheduled. These 153022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol //! events are in a queue to be distributed to apps. 154022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol static constexpr size_t kMaxUnscheduledEventCount = 1024; 155022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol 156e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie //! The instance ID that was previously generated by getNextInstanceId. 157e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie uint32_t mLastInstanceId = kSystemInstanceId; 158e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 1594927ee586656424c827920876673228fbdcf27c3Andrew Rossignol //! The memory pool to allocate incoming events from. 160f7914d0fbadf2644c0c4096380c741bee2a026e0Andrew Rossignol SynchronizedMemoryPool<Event, kMaxEventCount> mEventPool; 1614927ee586656424c827920876673228fbdcf27c3Andrew Rossignol 162fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol //! The timer used schedule timed events for tasks running in this event loop. 163fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol TimerPool mTimerPool; 164fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol 165c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol //! The list of nanoapps managed by this event loop. 1662de17c9c5c541d72248f8371dfb4d7e402dc93e8Andrew Rossignol DynamicVector<UniquePtr<Nanoapp>> mNanoapps; 167725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol 168977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie //! This lock *must* be held whenever we: 169977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie //! (1) make changes to the mNanoapps vector, or 170977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie //! (2) read the mNanoapps vector from a thread other than the one 171977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie //! associated with this EventLoop 172977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie //! It is not necessary to acquire the lock when reading mNanoapps from within 173977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie //! the thread context of this EventLoop. 174977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie Mutex mNanoappsLock; 175977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie 176c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol //! The blocking queue of incoming events from the system that have not been 177c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol //! distributed out to apps yet. 1781795db1e2282dac8454cf59d23314f70b6930f7bAndrew Rossignol FixedSizeBlockingQueue<Event *, kMaxUnscheduledEventCount> mEvents; 179e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 180977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie // TODO: should probably be atomic to be fully correct 181977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie volatile bool mRunning = false; 182e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 183e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie Nanoapp *mCurrentApp = nullptr; 184e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 185977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie /** 186977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Call after when an Event has been delivered to all intended recipients. 187977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Invokes the event's free callback (if given) and releases resources. 188977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * 189977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @param event The event to be freed 190977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie */ 191e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie void freeEvent(Event *event); 192e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 193977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie /** 194977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Finds a Nanoapp with the given instanceId. 195977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * 196977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * Only safe to call within this EventLoop's thread. 197977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * 198977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @param instanceId Nanoapp instance identifier 199977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * @return Nanoapp with the given instanceId, or nullptr if not found 200977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie */ 201977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie Nanoapp *lookupAppByInstanceId(uint32_t instanceId); 202e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie}; 203e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 204e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie} // namespace chre 205e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie 206e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#endif // CHRE_CORE_EVENT_LOOP_H_ 207