Expose OnRun to Rust

Change-Id: I2760992cbb98b3bf3b99c7246c4ac1557cf54a0f
Signed-off-by: Brian Silverman <bsilver16384@gmail.com>
diff --git a/aos/events/event_loop_runtime.h b/aos/events/event_loop_runtime.h
index df76d67..faa5ad7 100644
--- a/aos/events/event_loop_runtime.h
+++ b/aos/events/event_loop_runtime.h
@@ -124,20 +124,36 @@
   const std::unique_ptr<RawFetcher> fetcher_;
 };
 
+class EventLoopRuntime;
+
+class OnRunForRust {
+ public:
+  OnRunForRust(EventLoopRuntime *runtime);
+  ~OnRunForRust();
+
+  bool is_running() const;
+
+ private:
+  EventLoopRuntime *const runtime_;
+};
+
 class EventLoopRuntime {
  public:
   EventLoopRuntime(EventLoop *event_loop) : event_loop_(event_loop) {}
-  ~EventLoopRuntime() = default;
+  ~EventLoopRuntime() {
+    CHECK_EQ(child_count_, 0)
+        << ": Some child objects were not destroyed first";
+  }
 
   EventLoop *event_loop() { return event_loop_; }
 
   void spawn(std::unique_ptr<ApplicationFuture> task) {
     CHECK(!task_) << ": May only call spawn once";
     task_ = std::move(task);
-    // TODO(Brian): Do this once we've got OnRun support.
-    // DoPoll();
-    // TODO(Brian): Once we have OnRun support, should this move there or stay
-    // here unconditionally?
+    DoPoll();
+    // Just do this unconditionally, so we don't have to keep track of each
+    // OnRun to only do it once. If Rust doesn't use OnRun, it's harmless to do
+    // an extra poll.
     event_loop_->OnRun([this] { DoPoll(); });
   }
 
@@ -146,6 +162,8 @@
   }
   const Node *node() const { return event_loop_->node(); }
 
+  bool is_running() const { return event_loop_->is_running(); }
+
   // autocxx generates broken C++ code for `time_point`, see
   // https://github.com/google/autocxx/issues/787.
   int64_t monotonic_now() const {
@@ -175,7 +193,11 @@
     return FetcherForRust(event_loop_->MakeRawFetcher(channel));
   }
 
+  OnRunForRust MakeOnRun() { return OnRunForRust(this); }
+
  private:
+  friend class OnRunForRust;
+
   // Polls the top-level future once. This is what all the callbacks should do.
   void DoPoll() {
     if (task_) {
@@ -186,6 +208,8 @@
   EventLoop *const event_loop_;
 
   std::unique_ptr<ApplicationFuture> task_;
+
+  int child_count_ = 0;
 };
 
 }  // namespace aos