-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
MainThreadToken
to ensure file-dialogs only run on the main thread
- Loading branch information
Showing
26 changed files
with
223 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
[package] | ||
name = "re_capabilities" | ||
authors.workspace = true | ||
description = "Capability tokens for the Rerun code base." | ||
edition.workspace = true | ||
homepage.workspace = true | ||
include.workspace = true | ||
license.workspace = true | ||
publish = true | ||
readme = "README.md" | ||
repository.workspace = true | ||
rust-version.workspace = true | ||
version.workspace = true | ||
|
||
[lints] | ||
workspace = true | ||
|
||
[package.metadata.docs.rs] | ||
all-features = true | ||
|
||
|
||
[features] | ||
default = [] | ||
|
||
## Enable constructing the [`MainThreadToken`] from an [`egui::Ui`]. | ||
egui = ["dep:egui"] | ||
|
||
|
||
[dependencies] | ||
# Internal dependencies: | ||
|
||
# External dependencies: | ||
document-features.workspace = true | ||
egui = { workspace = true, default-features = false, optional = true } | ||
static_assertions.workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# re_capabilities | ||
|
||
Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. | ||
|
||
[![Latest version](https://img.shields.io/crates/v/re_capabilities.svg)](https://crates.io/crates/utils/re_capabilities) | ||
[![Documentation](https://docs.rs/re_capabilities/badge.svg)](https://docs.rs/re_capabilities) | ||
![MIT](https://img.shields.io/badge/license-MIT-blue.svg) | ||
![Apache](https://img.shields.io/badge/license-Apache-blue.svg) | ||
|
||
Specifies capability tokens, required by different parts of the code base. | ||
These are tokens passed down the call tree, to explicitly allow different capabilities in different parts of the code base. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
//! Specifies capability tokens, required by different parts of the code base. | ||
//! These are tokens passed down the call tree, to explicitly allow different capabilities in different parts of the code base. | ||
//! | ||
//! For instance, the [`MainThreadToken`] is taken by argument in functions that needs to run on the main thread. | ||
//! By requiring this token, you guarantee at compile-time that the function is only called on the main thread. | ||
//! | ||
//! All capability tokens should be created in the top-level of the call tree, | ||
//! (i.e. in `fn main`) and passed down to all functions that require it. | ||
//! That way you can be certain in what an area of code is allowed to do. | ||
//! | ||
//! See [`cap-std`](https://crates.io/crates/cap-std) for another capability-centric crate. | ||
//! | ||
//! ## Feature flags | ||
#![doc = document_features::document_features!()] | ||
//! | ||
mod main_thread_token; | ||
|
||
pub use main_thread_token::MainThreadToken; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use static_assertions::assert_not_impl_any; | ||
|
||
/// A token that proves we are on the main thread. | ||
/// | ||
/// Certain operations are only allowed on the main thread. | ||
/// These operations should require this token. | ||
/// For instance, any function using file dialogs (e.g. using [`rfd`](https://docs.rs/rfd/latest/rfd/)) should require this token. | ||
/// | ||
/// The token should only be constructed in `fn main`, using [`MainThreadToken::i_promise_i_am_on_the_main_thread`], | ||
/// and then be passed down the call tree to where it is needed. | ||
/// [`MainTheadToken`] is neither `Send` nor `Sync`, | ||
/// thus guaranteeing that it cannot be found in other threads. | ||
/// | ||
/// Of course, there is nothing stopping you from calling [`MainThreadToken::i_promise_i_am_on_the_main_thread`] from a background thread, | ||
/// but PLEASE DON'T DO THAT. | ||
/// In other words, don't use this as a guarantee for unsafe code. | ||
/// | ||
/// There is also [`MainThreadToken::from_egui_ui`] which uses the implicit guarantee of egui | ||
/// (which _usually_ is run on the main thread) to construct a [`MainThreadToken`]. | ||
/// Use this only in a code base where you are sure that egui is running only on the main thread. | ||
#[derive(Clone, Copy)] | ||
pub struct MainThreadToken { | ||
/// Prevent from being sent between threads. | ||
/// | ||
/// Workaround until `impl !Send for X {}` is stable. | ||
_dont_send_me: std::marker::PhantomData<*const ()>, | ||
} | ||
|
||
impl MainThreadToken { | ||
/// Only call this from `fn main`, or you may get weird runtime errors! | ||
pub fn i_promise_i_am_on_the_main_thread() -> Self { | ||
#[cfg(not(target_arch = "wasm32"))] | ||
debug_assert_eq!(std::thread::current().name(), Some("main"), | ||
"DEBUG ASSERT: Trying to construct a MainThreadToken on a thread that is not the main thread!" | ||
); | ||
|
||
Self { | ||
_dont_send_me: std::marker::PhantomData, | ||
} | ||
} | ||
|
||
/// We should only create an `egui::Ui` on the main thread, | ||
/// so having it is proof enough that we are on the main thread. | ||
/// | ||
/// Use this only in a code base where you are sure that egui is running only on the main thread. | ||
#[cfg(feature = "egui")] | ||
pub fn from_egui_ui(_ui: &egui::Ui) -> Self { | ||
Self::i_promise_i_am_on_the_main_thread() | ||
} | ||
} | ||
|
||
assert_not_impl_any!(MainThreadToken: Send, Sync); | ||
assert_not_impl_any!(&MainThreadToken: Send, Sync); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.