event_loop.h revision 30f18903edc1dfe46e12b9989760ef7a56cb31d3
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"
24c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol#include "chre/util/dynamic_vector.h"
25022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol#include "chre/util/fixed_size_blocking_queue.h"
26e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#include "chre/util/non_copyable.h"
27a1d5686c7513f6b8a436efd9f554d8c2227a2291Brian Duddie#include "chre/util/synchronized_memory_pool.h"
28e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
29e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddienamespace chre {
30e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
31e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie/**
32977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * The EventLoop represents a single thread of execution that is shared among
33977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * zero or more nanoapps. As the name implies, the EventLoop is built around a
34977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie * loop that delivers events to the nanoapps managed within for processing.
35e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie */
36e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddieclass EventLoop : public NonCopyable {
37e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie public:
38fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol  /**
39fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol   * Setup the event loop.
40fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol   */
41fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol  EventLoop();
42fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol
43977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  /**
44977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * Searches the set of nanoapps managed by this EventLoop for one with the
45977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * given app ID. If found, provides its instance ID, which can be used to send
46977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * events to the app.
47977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *
48977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * This function is safe to call from any thread.
49977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *
50977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @param appId The nanoapp identifier to search for.
51977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @param instanceId If this function returns true, will be populated with the
52977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *        instanceId associated with the given appId; otherwise unmodified.
53977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *        Must not be null.
54977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @return true if the given app ID was found and instanceId was populated
55977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   */
56977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  bool findNanoappInstanceIdByAppId(uint64_t appId, uint32_t *instanceId);
57e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
58e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  /**
59e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * Starts a nanoapp by invoking the start entry point. If this is successful,
60e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * the app is managed by the event loop and the pointer passed in must remain
61e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * valid.
62e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   *
63e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * @param A pointer to the nanoapp to start.
64e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * @return True if the app was started successfully.
65e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   */
66e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  bool startNanoapp(Nanoapp *nanoapp);
67e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
68e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  /**
69e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * Stops a nanoapp by invoking the stop entry point. The nanoapp passed in
70e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * must have been previously started by the startNanoapp method.
71e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   *
72e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * @param A pointer to the nanoapp to stop.
73e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   */
74e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  void stopNanoapp(Nanoapp *nanoapp);
75e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
76e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  /**
77977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * Executes the loop that blocks on the event queue and delivers received
78977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * events to nanoapps. Only returns after stop() is called (from another
79977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * context).
80e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   */
81e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  void run();
82e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
83e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  /**
84e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * Signals the event loop currently executing in run() to exit gracefully at
85f80ea015d077330cfdbd619680b250915ffcf1d2Brian Duddie   * the next available opportunity. This function is thread-safe.
86e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   */
87e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  void stop();
88e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
894927ee586656424c827920876673228fbdcf27c3Andrew Rossignol  /**
904927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   * Posts an event to a nanoapp that is currently running (or all nanoapps if
91042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie   * the target instance ID is kBroadcastInstanceId).
92042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie   *
93042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie   * This function is safe to call from any thread.
944927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   *
954927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   * @param The type of data being posted.
964927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   * @param The data being posted.
974927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   * @param The callback to invoke when the event is no longer needed.
984927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   * @param The instance ID of the sender of this event.
994927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   * @param The instance ID of the destination of this event.
1004927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   *
101042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie   * @return true if the event was successfully added to the queue
1024927ee586656424c827920876673228fbdcf27c3Andrew Rossignol   */
103042f73e3b7f019c818f69b2c097c4b6f9db839b5Brian Duddie  bool postEvent(uint16_t eventType, void *eventData,
1044927ee586656424c827920876673228fbdcf27c3Andrew Rossignol                 chreEventCompleteFunction *freeCallback,
1054927ee586656424c827920876673228fbdcf27c3Andrew Rossignol                 uint32_t senderInstanceId = kSystemInstanceId,
1064927ee586656424c827920876673228fbdcf27c3Andrew Rossignol                 uint32_t targetInstanceId = kBroadcastInstanceId);
107e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
108e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  /**
109e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * Returns a pointer to the currently executing Nanoapp, or nullptr if none is
110977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * currently executing. Must only be called from within the thread context
111977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * associated with this EventLoop.
112e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   *
113977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @return the currently executing nanoapp, or nullptr
114e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   */
1157983050d7cd84f1d5736f220ef9fd49be716b2c8Andrew Rossignol  Nanoapp *getCurrentNanoapp() const;
116e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
117e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  /**
118e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * Returns a guaranteed unique instance ID that can be used to construct a
119e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * nanoapp.
120e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   *
121e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   * @return a unique instance ID to assign to a nanoapp.
122e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie   */
123977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  // TODO: move this to EventLoopManager as it must be unique across all event
124977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  // loops; we currently really only support one EventLoop so it's OK for now
125e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  uint32_t getNextInstanceId();
126e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
127725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol  /**
128725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol   * Obtains the TimerPool associated with this event loop.
129725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol   *
130725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol   * @return The timer pool owned by this event loop.
131725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol   */
132725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol  TimerPool& getTimerPool();
133725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol
13430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  /**
13530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   * Searches the set of nanoapps managed by this EventLoop for one with the
13630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   * given instance ID.
13730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   *
13830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   * This function is safe to call from any thread.
13930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   *
14030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   * @param instanceId The nanoapp instance ID to search for.
14130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   * @return a pointer to the found nanoapp or nullptr if no match was found.
14230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol   */
14330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  Nanoapp *findNanoappByInstanceId(uint32_t instanceId);
14430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
145e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie private:
1464927ee586656424c827920876673228fbdcf27c3Andrew Rossignol  //! The maximum number of events that can be active in the system.
1474927ee586656424c827920876673228fbdcf27c3Andrew Rossignol  static constexpr size_t kMaxEventCount = 1024;
1484927ee586656424c827920876673228fbdcf27c3Andrew Rossignol
149022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol  //! The maximum number of events that are awaiting to be scheduled. These
150022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol  //! events are in a queue to be distributed to apps.
151022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol  static constexpr size_t kMaxUnscheduledEventCount = 1024;
152022cc6c770c299bb364e35377a2661791475bbceAndrew Rossignol
153e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  //! The instance ID that was previously generated by getNextInstanceId.
154e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  uint32_t mLastInstanceId = kSystemInstanceId;
155e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
1564927ee586656424c827920876673228fbdcf27c3Andrew Rossignol  //! The memory pool to allocate incoming events from.
157f7914d0fbadf2644c0c4096380c741bee2a026e0Andrew Rossignol  SynchronizedMemoryPool<Event, kMaxEventCount> mEventPool;
1584927ee586656424c827920876673228fbdcf27c3Andrew Rossignol
159fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol  //! The timer used schedule timed events for tasks running in this event loop.
160fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol  TimerPool mTimerPool;
161fbb213b072fec0a14f437ad55685c4d95eec829eAndrew Rossignol
162c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol  //! The list of nanoapps managed by this event loop.
1631795db1e2282dac8454cf59d23314f70b6930f7bAndrew Rossignol  DynamicVector<Nanoapp *> mNanoapps;
164725bef45ca127971b3ea798cd1f4e4b2c0d8fe9dAndrew Rossignol
165977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  //! This lock *must* be held whenever we:
166977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  //!   (1) make changes to the mNanoapps vector, or
167977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  //!   (2) read the mNanoapps vector from a thread other than the one
168977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  //!       associated with this EventLoop
169977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  //! It is not necessary to acquire the lock when reading mNanoapps from within
170977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  //! the thread context of this EventLoop.
171977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  Mutex mNanoappsLock;
172977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie
173c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol  //! The blocking queue of incoming events from the system that have not been
174c03d7df169f13195652de29f4452830130a0c53fAndrew Rossignol  //!  distributed out to apps yet.
1751795db1e2282dac8454cf59d23314f70b6930f7bAndrew Rossignol  FixedSizeBlockingQueue<Event *, kMaxUnscheduledEventCount> mEvents;
176e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
177977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  // TODO: should probably be atomic to be fully correct
178977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  volatile bool mRunning = false;
179e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
180e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  Nanoapp *mCurrentApp = nullptr;
181e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
182977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  /**
183977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * Call after when an Event has been delivered to all intended recipients.
184977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * Invokes the event's free callback (if given) and releases resources.
185977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *
186977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @param event The event to be freed
187977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   */
188e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie  void freeEvent(Event *event);
189e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
190977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  /**
191977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * Finds a Nanoapp with the given instanceId.
192977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *
193977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * Only safe to call within this EventLoop's thread.
194977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   *
195977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @param instanceId Nanoapp instance identifier
196977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   * @return Nanoapp with the given instanceId, or nullptr if not found
197977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie   */
198977321d9ad051d4d6519a5fa8c2ca914f4d1424fBrian Duddie  Nanoapp *lookupAppByInstanceId(uint32_t instanceId);
199e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie};
200e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
201e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie}  // namespace chre
202e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie
203e64f180233e64c40b56993cfea3696c5b4b16395Brian Duddie#endif  // CHRE_CORE_EVENT_LOOP_H_
204