Skip to content

Commit

Permalink
Desktop: Move universe task code from bin to lib.
Browse files Browse the repository at this point in the history
  • Loading branch information
kpreid committed Aug 26, 2024
1 parent d9e50af commit 7af85d8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 21 deletions.
22 changes: 4 additions & 18 deletions all-is-cubes-desktop/src/bin/all-is-cubes/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ use clap::{CommandFactory as _, Parser as _};
use all_is_cubes::euclid::Size2D;
use all_is_cubes::listen::ListenableCell;
use all_is_cubes_render::camera::{GraphicsOptions, Viewport};
use all_is_cubes_ui::notification;
use all_is_cubes_ui::vui::widgets::ProgressBarState;

#[cfg(feature = "record")]
use all_is_cubes_desktop::record;
Expand All @@ -26,7 +24,7 @@ use all_is_cubes_desktop::winit::{
self as aic_winit, create_winit_wgpu_desktop_session, winit_main_loop_and_init,
};
use all_is_cubes_desktop::{
inner_main, load_config, logging, DesktopSession, InnerMainParams, Session,
inner_main, load_config, logging, DesktopSession, InnerMainParams, Session, UniverseTask,
};

mod command_options;
Expand Down Expand Up @@ -91,14 +89,7 @@ fn main() -> Result<(), anyhow::Error> {

// Done with options; now start creating the session.

// Kick off constructing the universe in the background.
let (universe_future, universe_notif_tx) = {
let (n_tx, n_rx) = tokio::sync::oneshot::channel();
(
runtime.spawn(input_source.create_universe(precompute_light, n_rx)),
n_tx,
)
};
let mut universe_task = UniverseTask::new(&executor, input_source, precompute_light);

// This cell will be moved into the session after (possibly) being reset to the actual
// window size. This is a kludge because the `Session`'s `Vui` wants to be able to track
Expand All @@ -121,12 +112,7 @@ fn main() -> Result<(), anyhow::Error> {
);
// TODO: this code should live in the lib
session.graphics_options_mut().set(graphics_options);
if let Ok(n) = session.show_notification(notification::NotificationContent::Progress(
ProgressBarState::new(0.0),
)) {
// Ignore send error because the process might have finished and dropped the receiver.
_ = universe_notif_tx.send(n);
}
universe_task.attach_to_session(&mut session);
let session_done_time = Instant::now();
log::debug!(
"Initialized session ({:.3} s)",
Expand All @@ -145,7 +131,7 @@ fn main() -> Result<(), anyhow::Error> {
application_title: title_and_version(),
runtime,
before_loop_time: Instant::now(),
universe_future,
universe_task,
headless: options.is_headless(),
logging: late_logging,
#[cfg(feature = "record")]
Expand Down
45 changes: 42 additions & 3 deletions all-is-cubes-desktop/src/startup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use anyhow::Context as _;

use all_is_cubes::universe::Universe;
use all_is_cubes_ui::apps::{ExitMainTask, MainTaskContext};
use all_is_cubes_ui::notification;
use all_is_cubes_ui::vui::widgets::ProgressBarState;

use crate::glue::{Executor, Renderer, Window};
use crate::{logging, record};
Expand All @@ -28,7 +30,7 @@ pub fn inner_main<Ren: Renderer, Win: Window>(
application_title,
runtime,
before_loop_time,
universe_future,
universe_task,
headless,
logging,
recording,
Expand Down Expand Up @@ -78,7 +80,7 @@ pub fn inner_main<Ren: Renderer, Win: Window>(
}

dsession.session.set_main_task(|mut ctx| async move {
let universe_result: Result<Universe, anyhow::Error> = match universe_future.await {
let universe_result: Result<Universe, anyhow::Error> = match universe_task.future.await {
Ok(Ok(u)) => Ok(u),
Ok(Err(e)) => {
Err(e).context("failed to create universe from requested template or file")
Expand Down Expand Up @@ -185,7 +187,7 @@ pub struct InnerMainParams {
pub application_title: String,
pub runtime: tokio::runtime::Runtime,
pub before_loop_time: Instant,
pub universe_future: tokio::task::JoinHandle<Result<Universe, anyhow::Error>>,
pub universe_task: UniverseTask,
pub headless: bool,
/// Result of calling [`logging::install()`], which should be done as early as feasible.
pub logging: logging::LateLogging,
Expand All @@ -201,6 +203,43 @@ pub struct InnerMainParams {
pub task_done_signal: tokio::sync::oneshot::Sender<()>,
}

/// An async task that constructs a [`Universe`] that will belong to a [`DesktopSession`],
/// delivered via [`InnerMainParams`].
#[derive(Debug)]
pub struct UniverseTask {
future: tokio::task::JoinHandle<Result<Universe, anyhow::Error>>,
progress_notification_handoff_tx:
Option<tokio::sync::oneshot::Sender<notification::Notification>>,
}

#[allow(missing_docs)] // sloppy API anyway
impl UniverseTask {
pub fn new(executor: &Executor, source: crate::UniverseSource, precompute_light: bool) -> Self {
// Kick off constructing the universe in the background.
let (n_tx, n_rx) = tokio::sync::oneshot::channel();
let future = executor
.tokio()
.spawn(source.create_universe(precompute_light, n_rx));
Self {
future,
progress_notification_handoff_tx: Some(n_tx),
}
}

pub fn attach_to_session(&mut self, session: &mut crate::Session) {
if let Ok(n) = session.show_notification(notification::NotificationContent::Progress(
ProgressBarState::new(0.0),
)) {
// Ignore send error because the process might have finished and dropped the receiver.
_ = self
.progress_notification_handoff_tx
.take()
.expect("attach_to_session() must be called only once")
.send(n);
}
}
}

#[allow(clippy::needless_pass_by_value)]
fn report_error_and_exit(_ctx: &MainTaskContext, error: anyhow::Error) -> ! {
// TODO: if we are a GUI-no-terminal session, log this instead of printing and create a dialog
Expand Down

0 comments on commit 7af85d8

Please sign in to comment.