Move ExitHandle into EventLoopRuntime

This is needed to reuse the ExitHandle with other event loop types.

Change-Id: Icf8d7be5ddb11f5994892f48aa2549f8900e33a3
Signed-off-by: Adam Snaider <adsnaider@gmail.com>
diff --git a/aos/events/event_loop_runtime.rs b/aos/events/event_loop_runtime.rs
index 023cfb6..7f58dbb 100644
--- a/aos/events/event_loop_runtime.rs
+++ b/aos/events/event_loop_runtime.rs
@@ -61,7 +61,7 @@
 };
 use cxx::UniquePtr;
 use flatbuffers::{root_unchecked, Follow, FollowWith, FullyQualifiedName};
-use futures::{future::FusedFuture, never::Never};
+use futures::{future::pending, future::FusedFuture, never::Never};
 use thiserror::Error;
 use uuid::Uuid;
 
@@ -69,6 +69,7 @@
 use aos_configuration::{ChannelLookupError, ConfigurationExt};
 
 pub use aos_uuid::UUID;
+pub use ffi::aos::ExitHandle as CppExitHandle;
 
 autocxx::include_cpp! (
 #include "aos/events/event_loop_runtime.h"
@@ -82,6 +83,7 @@
 generate!("aos::FetcherForRust")
 generate!("aos::OnRunForRust")
 generate!("aos::EventLoopRuntime")
+generate!("aos::ExitHandle")
 
 subclass!("aos::ApplicationFuture", RustApplicationFuture)
 
@@ -1194,3 +1196,28 @@
 }
 
 use panic_waker::panic_waker;
+
+pub struct ExitHandle(UniquePtr<CppExitHandle>);
+
+impl ExitHandle {
+    /// Exits the EventLoops represented by this handle. You probably want to immediately return
+    /// from the context this is called in. Awaiting [`exit`] instead of using this function is an
+    /// easy way to do that.
+    pub fn exit_sync(mut self) {
+        self.0.as_mut().unwrap().Exit();
+    }
+
+    /// Exits the EventLoops represented by this handle, and never returns. Immediately awaiting
+    /// this from a [`EventLoopRuntime::spawn`]ed task is usually what you want, it will ensure
+    /// that no more code from that task runs.
+    pub async fn exit(self) -> Never {
+        self.exit_sync();
+        pending().await
+    }
+}
+
+impl From<UniquePtr<CppExitHandle>> for ExitHandle {
+    fn from(inner: UniquePtr<ffi::aos::ExitHandle>) -> Self {
+        Self(inner)
+    }
+}
diff --git a/aos/events/simulated_event_loop.rs b/aos/events/simulated_event_loop.rs
index 06fcee8..e0be773 100644
--- a/aos/events/simulated_event_loop.rs
+++ b/aos/events/simulated_event_loop.rs
@@ -8,12 +8,11 @@
 
 use autocxx::WithinBox;
 use cxx::UniquePtr;
-use futures::{future::pending, never::Never};
 
 pub use aos_configuration::{Channel, Configuration, ConfigurationExt, Node};
 use aos_configuration_fbs::aos::Configuration as RustConfiguration;
-pub use aos_events_event_loop_runtime::EventLoop;
 use aos_events_event_loop_runtime::EventLoopRuntime;
+pub use aos_events_event_loop_runtime::{CppExitHandle, EventLoop, ExitHandle};
 use aos_flatbuffers::{transmute_table_to, Flatbuffer};
 
 autocxx::include_cpp! (
@@ -22,9 +21,9 @@
 
 safety!(unsafe)
 
-generate!("aos::ExitHandle")
 generate!("aos::SimulatedEventLoopFactoryForRust")
 
+extern_cpp_type!("aos::ExitHandle", crate::CppExitHandle)
 extern_cpp_type!("aos::Configuration", crate::Configuration)
 extern_cpp_type!("aos::Node", crate::Node)
 extern_cpp_type!("aos::EventLoop", crate::EventLoop)
@@ -92,7 +91,7 @@
     }
 
     pub fn make_exit_handle(&mut self) -> ExitHandle {
-        ExitHandle(self.as_mut().MakeExitHandle())
+        self.as_mut().MakeExitHandle().into()
     }
 
     pub fn run(&mut self) {
@@ -104,27 +103,6 @@
     // pub fn spawn_on_startup(&mut self, spawner: impl FnMut());
 }
 
-// TODO(Brian): Move this and the `generate!` somewhere else once we wrap ShmEventLoop, which also
-// uses it.
-pub struct ExitHandle(UniquePtr<ffi::aos::ExitHandle>);
-
-impl ExitHandle {
-    /// Exits the EventLoops represented by this handle. You probably want to immediately return
-    /// from the context this is called in. Awaiting [`exit`] instead of using this function is an
-    /// easy way to do that.
-    pub fn exit_sync(mut self) {
-        self.0.as_mut().unwrap().Exit();
-    }
-
-    /// Exits the EventLoops represented by this handle, and never returns. Immediately awaiting
-    /// this from a [`EventLoopRuntime::spawn`]ed task is usually what you want, it will ensure
-    /// that no more code from that task runs.
-    pub async fn exit(self) -> Never {
-        self.exit_sync();
-        pending().await
-    }
-}
-
 pub struct SimulatedEventLoopRuntime(ManuallyDrop<EventLoopRuntime<'static>>);
 
 impl SimulatedEventLoopRuntime {