Make event_loop_runtime const mutable

The idea is that the C++ bindings should use Rust's
mutation paradigm to more closely match the ideas of
shared and exclusive references correctly.

This is particularly important since we need to have
multiple references to the event loop (from different)
async contexts, so requiring the use of exclusive
references won't work and is not how it works in C++.

Change-Id: I232955cba0e83cd4b1ec71207bb6d06d46eaf5e5
Signed-off-by: James Kuszmaul <james.kuszmaul@bluerivertech.com>
diff --git a/aos/events/event_loop_runtime.cc b/aos/events/event_loop_runtime.cc
index e3d73c1..790fe9e 100644
--- a/aos/events/event_loop_runtime.cc
+++ b/aos/events/event_loop_runtime.cc
@@ -2,13 +2,15 @@
 
 namespace aos {
 
-OnRunForRust::OnRunForRust(EventLoopRuntime *runtime) : runtime_(runtime) {
+OnRunForRust::OnRunForRust(const EventLoopRuntime *runtime)
+    : runtime_(runtime) {
   ++runtime->child_count_;
 }
 OnRunForRust::~OnRunForRust() { --runtime_->child_count_; }
 bool OnRunForRust::is_running() const { return runtime_->is_running(); }
 
-std::unique_ptr<TimerForRust> TimerForRust::Make(EventLoopRuntime *runtime) {
+std::unique_ptr<TimerForRust> TimerForRust::Make(
+    const EventLoopRuntime *runtime) {
   auto handler = std::unique_ptr<TimerForRust>(new TimerForRust());
   TimerForRust *inner = handler.get();
   handler->timer_ = runtime->event_loop()->AddTimer([inner, runtime] {
diff --git a/aos/events/event_loop_runtime.h b/aos/events/event_loop_runtime.h
index 7cc551f..4d284c2 100644
--- a/aos/events/event_loop_runtime.h
+++ b/aos/events/event_loop_runtime.h
@@ -131,18 +131,18 @@
 
 class OnRunForRust {
  public:
-  OnRunForRust(EventLoopRuntime *runtime);
+  OnRunForRust(const EventLoopRuntime *runtime);
   ~OnRunForRust();
 
   bool is_running() const;
 
  private:
-  EventLoopRuntime *const runtime_;
+  const EventLoopRuntime *const runtime_;
 };
 
 class TimerForRust {
  public:
-  static std::unique_ptr<TimerForRust> Make(EventLoopRuntime *runtime);
+  static std::unique_ptr<TimerForRust> Make(const EventLoopRuntime *runtime);
 
   TimerForRust(const TimerForRust &) = delete;
   TimerForRust(TimerForRust &&) = delete;
@@ -185,9 +185,9 @@
         << ": Some child objects were not destroyed first";
   }
 
-  EventLoop *event_loop() { return event_loop_; }
+  EventLoop *event_loop() const { return event_loop_; }
 
-  void Spawn(std::unique_ptr<ApplicationFuture> task) {
+  void Spawn(std::unique_ptr<ApplicationFuture> task) const {
     CHECK(!task_) << ": May only call Spawn once";
     task_ = std::move(task);
     DoPoll();
@@ -219,30 +219,32 @@
 
   rust::Str name() const { return StringViewToRustStr(event_loop_->name()); }
 
-  WatcherForRust MakeWatcher(const Channel *channel) {
+  WatcherForRust MakeWatcher(const Channel *channel) const {
     event_loop_->MakeRawNoArgWatcher(channel,
                                      [this](const Context &) { DoPoll(); });
     return WatcherForRust(event_loop_->MakeRawFetcher(channel));
   }
 
-  SenderForRust MakeSender(const Channel *channel) {
+  SenderForRust MakeSender(const Channel *channel) const {
     return SenderForRust(event_loop_->MakeRawSender(channel));
   }
 
-  FetcherForRust MakeFetcher(const Channel *channel) {
+  FetcherForRust MakeFetcher(const Channel *channel) const {
     return FetcherForRust(event_loop_->MakeRawFetcher(channel));
   }
 
-  OnRunForRust MakeOnRun() { return OnRunForRust(this); }
+  OnRunForRust MakeOnRun() const { return OnRunForRust(this); }
 
-  std::unique_ptr<TimerForRust> AddTimer() { return TimerForRust::Make(this); }
+  std::unique_ptr<TimerForRust> AddTimer() const {
+    return TimerForRust::Make(this);
+  }
 
  private:
   friend class OnRunForRust;
   friend class TimerForRust;
 
   // Polls the top-level future once. This is what all the callbacks should do.
-  void DoPoll() {
+  void DoPoll() const {
     if (task_) {
       CHECK(task_->Poll()) << ": Rust panic, aborting";
     }
@@ -250,9 +252,20 @@
 
   EventLoop *const event_loop_;
 
-  std::unique_ptr<ApplicationFuture> task_;
+  // For Rust's EventLoopRuntime to be semantically equivelant to C++'s event
+  // loop, we need the ability to have shared references (&EventLoopRuntime) on
+  // the Rust side. Without that, the API would be overly restrictive to be
+  // usable. In order for the generated code to use &self references on methods,
+  // they need to be marked `const` on the C++ side. We use the `mutable`
+  // keyword to allow mutation through `const` methods.
+  //
+  // SAFETY:
+  //   * The event loop runtime must be `!Sync` in the Rust side (default).
+  //   * We can't expose exclusive references (&mut) to either of the mutable
+  //     fields on the Rust side from a shared reference (&).
+  mutable std::unique_ptr<ApplicationFuture> task_;
 
-  int child_count_ = 0;
+  mutable int child_count_ = 0;
 };
 
 }  // namespace aos
diff --git a/aos/events/event_loop_runtime.rs b/aos/events/event_loop_runtime.rs
index 35a4225..1a6beb7 100644
--- a/aos/events/event_loop_runtime.rs
+++ b/aos/events/event_loop_runtime.rs
@@ -259,7 +259,7 @@
 
 impl<T: EventLoopHolder> Drop for EventLoopRuntimeHolder<T> {
     fn drop(&mut self) {
-        let event_loop = self.0.as_mut().event_loop();
+        let event_loop = self.0.event_loop();
         // SAFETY: We're not going to touch this field again. The underlying EventLoop will not be
         // run again because we're going to drop it next.
         unsafe { ManuallyDrop::drop(&mut self.0) };
@@ -399,8 +399,8 @@
     ///
     /// The returned value should only be used for destroying it (_after_ `self` is dropped) or
     /// calling other C++ APIs.
-    pub fn raw_event_loop(&mut self) -> *mut ffi::aos::EventLoop {
-        self.0.as_mut().event_loop()
+    pub fn raw_event_loop(&self) -> *mut ffi::aos::EventLoop {
+        self.0.event_loop()
     }
 
     /// Returns a reference to the name of this EventLoop.
@@ -563,8 +563,8 @@
     /// }});
     /// # }
     /// ```
-    pub fn spawn(&mut self, task: impl Future<Output = Never> + 'event_loop) {
-        self.0.as_mut().Spawn(RustApplicationFuture::new(task));
+    pub fn spawn(&self, task: impl Future<Output = Never> + 'event_loop) {
+        self.0.Spawn(RustApplicationFuture::new(task));
     }
 
     pub fn configuration(&self) -> &'event_loop Configuration {
@@ -590,10 +590,10 @@
     /// # Panics
     ///
     /// Dropping `self` before the returned object is dropped will panic.
-    pub fn make_raw_watcher(&mut self, channel: &'event_loop Channel) -> RawWatcher {
+    pub fn make_raw_watcher(&self, channel: &'event_loop Channel) -> RawWatcher {
         // SAFETY: `channel` is valid for the necessary lifetime, all other requirements fall under
         // the usual autocxx heuristics.
-        RawWatcher(unsafe { self.0.as_mut().MakeWatcher(channel) }.within_box())
+        RawWatcher(unsafe { self.0.MakeWatcher(channel) }.within_box())
     }
 
     /// Provides type-safe async blocking access to messages on a channel. `T` should be a
@@ -603,7 +603,7 @@
     /// # Panics
     ///
     /// Dropping `self` before the returned object is dropped will panic.
-    pub fn make_watcher<T>(&mut self, channel_name: &str) -> Result<Watcher<T>, ChannelLookupError>
+    pub fn make_watcher<T>(&self, channel_name: &str) -> Result<Watcher<T>, ChannelLookupError>
     where
         for<'a> T: FollowWith<'a>,
         for<'a> <T as FollowWith<'a>>::Inner: Follow<'a>,
@@ -619,10 +619,10 @@
     /// # Panics
     ///
     /// Dropping `self` before the returned object is dropped will panic.
-    pub fn make_raw_sender(&mut self, channel: &'event_loop Channel) -> RawSender {
+    pub fn make_raw_sender(&self, channel: &'event_loop Channel) -> RawSender {
         // SAFETY: `channel` is valid for the necessary lifetime, all other requirements fall under
         // the usual autocxx heuristics.
-        RawSender(unsafe { self.0.as_mut().MakeSender(channel) }.within_box())
+        RawSender(unsafe { self.0.MakeSender(channel) }.within_box())
     }
 
     /// Allows sending messages on a channel with a type-safe API.
@@ -630,7 +630,7 @@
     /// # Panics
     ///
     /// Dropping `self` before the returned object is dropped will panic.
-    pub fn make_sender<T>(&mut self, channel_name: &str) -> Result<Sender<T>, ChannelLookupError>
+    pub fn make_sender<T>(&self, channel_name: &str) -> Result<Sender<T>, ChannelLookupError>
     where
         for<'a> T: FollowWith<'a>,
         for<'a> <T as FollowWith<'a>>::Inner: Follow<'a>,
@@ -646,10 +646,10 @@
     /// # Panics
     ///
     /// Dropping `self` before the returned object is dropped will panic.
-    pub fn make_raw_fetcher(&mut self, channel: &'event_loop Channel) -> RawFetcher {
+    pub fn make_raw_fetcher(&self, channel: &'event_loop Channel) -> RawFetcher {
         // SAFETY: `channel` is valid for the necessary lifetime, all other requirements fall under
         // the usual autocxx heuristics.
-        RawFetcher(unsafe { self.0.as_mut().MakeFetcher(channel) }.within_box())
+        RawFetcher(unsafe { self.0.MakeFetcher(channel) }.within_box())
     }
 
     /// Provides type-safe access to messages on a channel, without the ability to wait for a new
@@ -659,7 +659,7 @@
     /// # Panics
     ///
     /// Dropping `self` before the returned object is dropped will panic.
-    pub fn make_fetcher<T>(&mut self, channel_name: &str) -> Result<Fetcher<T>, ChannelLookupError>
+    pub fn make_fetcher<T>(&self, channel_name: &str) -> Result<Fetcher<T>, ChannelLookupError>
     where
         for<'a> T: FollowWith<'a>,
         for<'a> <T as FollowWith<'a>>::Inner: Follow<'a>,
@@ -676,8 +676,8 @@
     /// subsequent code will have any realtime scheduling applied. This means it can rely on
     /// consistent timing, but it can no longer create any EventLoop child objects or do anything
     /// else non-realtime.
-    pub fn on_run(&mut self) -> OnRun {
-        OnRun(self.0.as_mut().MakeOnRun().within_box())
+    pub fn on_run(&self) -> OnRun {
+        OnRun(self.0.MakeOnRun().within_box())
     }
 
     pub fn is_running(&self) -> bool {
@@ -685,12 +685,12 @@
     }
 
     /// Returns an unarmed timer.
-    pub fn add_timer(&mut self) -> Timer {
-        Timer(self.0.as_mut().AddTimer())
+    pub fn add_timer(&self) -> Timer {
+        Timer(self.0.AddTimer())
     }
 
     /// Returns a timer that goes off every `duration`-long ticks.
-    pub fn add_interval(&mut self, duration: Duration) -> Timer {
+    pub fn add_interval(&self, duration: Duration) -> Timer {
         let mut timer = self.add_timer();
         timer.setup(self.monotonic_now(), Some(duration));
         timer