blob: 79101ded7b2802a9b6dd4f5be834406e91fbc8e0 [file] [log] [blame]
Austin Schuh520f33d2019-01-27 22:38:01 -08001#ifndef AOS_EVENTS_SHM_EVENT_LOOP_H_
2#define AOS_EVENTS_SHM_EVENT_LOOP_H_
3
Parker Schuhe4a70d62017-12-27 20:10:20 -08004#include <unordered_set>
5#include <vector>
Austin Schuh6b6dfa52019-06-12 20:16:20 -07006
John Park33858a32018-09-28 23:05:48 -07007#include "aos/condition.h"
Austin Schuh6b6dfa52019-06-12 20:16:20 -07008#include "aos/events/epoll.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08009#include "aos/events/event-loop.h"
Austin Schuh6b6dfa52019-06-12 20:16:20 -070010#include "aos/mutex/mutex.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -080011
12namespace aos {
13namespace internal {
14
15class WatcherThreadState;
Neil Balch229001a2018-01-07 18:22:52 -080016class TimerHandlerState;
Parker Schuhe4a70d62017-12-27 20:10:20 -080017
18} // namespace internal
19
Neil Balchc8f41ed2018-01-20 22:06:53 -080020// Specialization of EventLoop that is built from queues running out of shared
John Park33858a32018-09-28 23:05:48 -070021// memory. See more details at aos/queue.h
Austin Schuh81fc9cc2019-02-02 23:25:47 -080022//
23// This object must be interacted with from one thread, but the Senders and
24// Fetchers may be used from multiple threads afterwords (as long as their
25// destructors are called back in one thread again)
Parker Schuhe4a70d62017-12-27 20:10:20 -080026class ShmEventLoop : public EventLoop {
27 public:
28 ShmEventLoop();
29 ~ShmEventLoop() override;
30
31 ::aos::monotonic_clock::time_point monotonic_now() override {
32 return ::aos::monotonic_clock::now();
33 }
34
Austin Schuh6b6dfa52019-06-12 20:16:20 -070035 ::std::unique_ptr<RawSender> MakeRawSender(
36 const ::std::string &path, const QueueTypeInfo &type) override;
37 ::std::unique_ptr<RawFetcher> MakeRawFetcher(
38 const ::std::string &path, const QueueTypeInfo &type) override;
Parker Schuhe4a70d62017-12-27 20:10:20 -080039
40 void MakeRawWatcher(
Austin Schuh6b6dfa52019-06-12 20:16:20 -070041 const ::std::string &path, const QueueTypeInfo &type,
42 ::std::function<void(const aos::Message *message)> watcher) override;
Parker Schuhe4a70d62017-12-27 20:10:20 -080043
Neil Balch229001a2018-01-07 18:22:52 -080044 TimerHandler *AddTimer(::std::function<void()> callback) override;
45
Austin Schuh6b6dfa52019-06-12 20:16:20 -070046 void OnRun(::std::function<void()> on_run) override;
Parker Schuhe4a70d62017-12-27 20:10:20 -080047 void Run() override;
48 void Exit() override;
49
Austin Schuh6b6dfa52019-06-12 20:16:20 -070050 // TODO(austin): Add a function to register control-C call.
51
Austin Schuh3115a202019-05-27 21:02:14 -070052 void SetRuntimeRealtimePriority(int priority) override {
53 if (is_running()) {
54 ::aos::Die("Cannot set realtime priority while running.");
55 }
Austin Schuh6b6dfa52019-06-12 20:16:20 -070056 thread_state_.priority_ = priority;
Austin Schuh3115a202019-05-27 21:02:14 -070057 }
58
Parker Schuhe4a70d62017-12-27 20:10:20 -080059 private:
60 friend class internal::WatcherThreadState;
Neil Balch229001a2018-01-07 18:22:52 -080061 friend class internal::TimerHandlerState;
Parker Schuhe4a70d62017-12-27 20:10:20 -080062 // This ThreadState ensures that two watchers in the same loop cannot be
63 // triggered concurrently. Because watchers block threads indefinitely, this
64 // has to be shared_ptr in case the EventLoop is destroyed before the thread
65 // receives any new events.
66 class ThreadState {
67 public:
68 void WaitForStart();
69
70 bool is_running() { return loop_running_; }
71
Austin Schuh6b6dfa52019-06-12 20:16:20 -070072 void Start();
Parker Schuhe4a70d62017-12-27 20:10:20 -080073
74 void Exit();
75
Austin Schuh3115a202019-05-27 21:02:14 -070076 void MaybeSetCurrentThreadRealtimePriority();
77
Parker Schuhe4a70d62017-12-27 20:10:20 -080078 private:
79 friend class internal::WatcherThreadState;
Neil Balch229001a2018-01-07 18:22:52 -080080 friend class internal::TimerHandlerState;
Parker Schuhe4a70d62017-12-27 20:10:20 -080081 friend class ShmEventLoop;
82
83 // This mutex ensures that only one watch event happens at a time.
Austin Schuh6b6dfa52019-06-12 20:16:20 -070084 ::aos::Mutex mutex_;
Parker Schuhe4a70d62017-12-27 20:10:20 -080085 // Block on this until the loop starts.
Austin Schuh6b6dfa52019-06-12 20:16:20 -070086 ::aos::Condition loop_running_cond_{&mutex_};
Parker Schuhe4a70d62017-12-27 20:10:20 -080087 // Used to notify watchers that the loop is done.
Austin Schuh6b6dfa52019-06-12 20:16:20 -070088 ::std::atomic<bool> loop_running_{false};
Parker Schuhe4a70d62017-12-27 20:10:20 -080089 bool loop_finished_ = false;
Austin Schuh3115a202019-05-27 21:02:14 -070090 int priority_ = -1;
Parker Schuhe4a70d62017-12-27 20:10:20 -080091 };
92
Austin Schuh6b6dfa52019-06-12 20:16:20 -070093 // Tracks that we can't have multiple watchers or a sender and a watcher (or
94 // multiple senders) on a single queue (path).
95 void Take(const ::std::string &path);
Parker Schuhe4a70d62017-12-27 20:10:20 -080096
Austin Schuh6b6dfa52019-06-12 20:16:20 -070097 ::std::vector<::std::function<void()>> on_run_;
98 ThreadState thread_state_;
99 ::std::vector<::std::string> taken_;
100 internal::EPoll epoll_;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800101
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700102 ::std::vector<::std::unique_ptr<internal::TimerHandlerState>> timers_;
103 ::std::vector<::std::unique_ptr<internal::WatcherThreadState>> watchers_;
Parker Schuhe4a70d62017-12-27 20:10:20 -0800104};
105
106} // namespace aos
Austin Schuh520f33d2019-01-27 22:38:01 -0800107
108#endif // AOS_EVENTS_SHM_EVENT_LOOP_H_