Place hot reloading behind hot feature flag
This commit is contained in:
parent
699b85762b
commit
e689ec13a6
3 changed files with 81 additions and 64 deletions
|
|
@ -41,10 +41,12 @@ qr_code = ["iced_widget/qr_code"]
|
||||||
markdown = ["iced_widget/markdown"]
|
markdown = ["iced_widget/markdown"]
|
||||||
# Enables lazy widgets
|
# Enables lazy widgets
|
||||||
lazy = ["iced_widget/lazy"]
|
lazy = ["iced_widget/lazy"]
|
||||||
# Enables a debug view in native platforms (press F12)
|
# Enables debug metrics in native platforms (press F12)
|
||||||
debug = ["iced_winit/debug", "iced_devtools"]
|
debug = ["iced_winit/debug", "iced_devtools"]
|
||||||
# Enables time-travel debugging (very experimental!)
|
# Enables time-travel debugging (very experimental!)
|
||||||
time-travel = ["debug", "iced_devtools/time-travel"]
|
time-travel = ["debug", "iced_devtools/time-travel"]
|
||||||
|
# Enables hot reloading (very experimental!)
|
||||||
|
hot = ["debug", "iced_debug/hot"]
|
||||||
# Enables the `thread-pool` futures executor as the `executor::Default` on native platforms
|
# Enables the `thread-pool` futures executor as the `executor::Default` on native platforms
|
||||||
thread-pool = ["iced_futures/thread-pool"]
|
thread-pool = ["iced_futures/thread-pool"]
|
||||||
# Enables `tokio` as the `executor::Default` on native platforms
|
# Enables `tokio` as the `executor::Default` on native platforms
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ categories.workspace = true
|
||||||
keywords.workspace = true
|
keywords.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
enable = ["dep:iced_beacon", "dep:cargo-hot"]
|
enable = ["dep:iced_beacon"]
|
||||||
|
hot = ["enable", "dep:cargo-hot"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced_core.workspace = true
|
iced_core.workspace = true
|
||||||
|
|
|
||||||
138
debug/src/lib.rs
138
debug/src/lib.rs
|
|
@ -39,6 +39,7 @@ pub fn disable() {
|
||||||
|
|
||||||
pub fn init(metadata: Metadata) {
|
pub fn init(metadata: Metadata) {
|
||||||
internal::init(metadata);
|
internal::init(metadata);
|
||||||
|
hot::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quit() -> bool {
|
pub fn quit() -> bool {
|
||||||
|
|
@ -114,15 +115,15 @@ pub fn commands() -> Subscription<Command> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hot<O>(f: impl FnOnce() -> O) -> O {
|
pub fn hot<O>(f: impl FnOnce() -> O) -> O {
|
||||||
internal::hot(f)
|
hot::call(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_hotpatch(f: impl Fn() + Send + Sync + 'static) {
|
pub fn on_hotpatch(f: impl Fn() + Send + Sync + 'static) {
|
||||||
internal::on_hotpatch(f)
|
hot::on_hotpatch(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_stale() -> bool {
|
pub fn is_stale() -> bool {
|
||||||
internal::is_stale()
|
hot::is_stale()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "enable", not(target_arch = "wasm32")))]
|
#[cfg(all(feature = "enable", not(target_arch = "wasm32")))]
|
||||||
|
|
@ -140,16 +141,8 @@ mod internal {
|
||||||
use beacon::span;
|
use beacon::span;
|
||||||
use beacon::span::present;
|
use beacon::span::present;
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
|
||||||
use std::sync::atomic::{self, AtomicBool, AtomicUsize};
|
use std::sync::atomic::{self, AtomicBool, AtomicUsize};
|
||||||
use std::sync::{Arc, LazyLock, Mutex, OnceLock, RwLock};
|
use std::sync::{LazyLock, RwLock};
|
||||||
|
|
||||||
static IS_STALE: AtomicBool = AtomicBool::new(false);
|
|
||||||
|
|
||||||
static HOT_FUNCTIONS_PENDING: Mutex<BTreeSet<u64>> =
|
|
||||||
Mutex::new(BTreeSet::new());
|
|
||||||
|
|
||||||
static HOT_FUNCTIONS: OnceLock<BTreeSet<u64>> = OnceLock::new();
|
|
||||||
|
|
||||||
pub fn init(metadata: Metadata) {
|
pub fn init(metadata: Metadata) {
|
||||||
let name = metadata.name.split("::").next().unwrap_or(metadata.name);
|
let name = metadata.name.split("::").next().unwrap_or(metadata.name);
|
||||||
|
|
@ -160,22 +153,6 @@ mod internal {
|
||||||
theme: metadata.theme,
|
theme: metadata.theme,
|
||||||
can_time_travel: metadata.can_time_travel,
|
can_time_travel: metadata.can_time_travel,
|
||||||
};
|
};
|
||||||
|
|
||||||
cargo_hot::connect();
|
|
||||||
|
|
||||||
cargo_hot::subsecond::register_handler(Arc::new(|| {
|
|
||||||
if HOT_FUNCTIONS.get().is_none() {
|
|
||||||
HOT_FUNCTIONS
|
|
||||||
.set(std::mem::take(
|
|
||||||
&mut HOT_FUNCTIONS_PENDING
|
|
||||||
.lock()
|
|
||||||
.expect("Lock hot functions"),
|
|
||||||
))
|
|
||||||
.expect("Set hot functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
IS_STALE.store(false, atomic::Ordering::Relaxed);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quit() -> bool {
|
pub fn quit() -> bool {
|
||||||
|
|
@ -307,39 +284,6 @@ mod internal {
|
||||||
Subscription::run(listen_for_commands)
|
Subscription::run(listen_for_commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hot<O>(f: impl FnOnce() -> O) -> O {
|
|
||||||
let mut f = Some(f);
|
|
||||||
|
|
||||||
// The `move` here is important. Hotpatching will not work
|
|
||||||
// otherwise.
|
|
||||||
let mut f = cargo_hot::subsecond::HotFn::current(move || {
|
|
||||||
f.take().expect("Hot function is stale")()
|
|
||||||
});
|
|
||||||
|
|
||||||
let address = f.ptr_address().0;
|
|
||||||
|
|
||||||
if let Some(hot_functions) = HOT_FUNCTIONS.get() {
|
|
||||||
if hot_functions.contains(&address) {
|
|
||||||
IS_STALE.store(true, atomic::Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let _ = HOT_FUNCTIONS_PENDING
|
|
||||||
.lock()
|
|
||||||
.expect("Lock hot functions")
|
|
||||||
.insert(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
f.call(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_hotpatch(f: impl Fn() + Send + Sync + 'static) {
|
|
||||||
cargo_hot::subsecond::register_handler(Arc::new(f));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_stale() -> bool {
|
|
||||||
IS_STALE.load(atomic::Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn span(span: span::Stage) -> Span {
|
fn span(span: span::Stage) -> Span {
|
||||||
log(client::Event::SpanStarted(span.clone()));
|
log(client::Event::SpanStarted(span.clone()));
|
||||||
|
|
||||||
|
|
@ -467,8 +411,78 @@ mod internal {
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn finish(self) {}
|
pub fn finish(self) {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hot<O>(f: impl FnOnce() -> O) -> O {
|
#[cfg(feature = "hot")]
|
||||||
|
mod hot {
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::sync::atomic::{self, AtomicBool};
|
||||||
|
use std::sync::{Arc, Mutex, OnceLock};
|
||||||
|
|
||||||
|
static IS_STALE: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
static HOT_FUNCTIONS_PENDING: Mutex<BTreeSet<u64>> =
|
||||||
|
Mutex::new(BTreeSet::new());
|
||||||
|
|
||||||
|
static HOT_FUNCTIONS: OnceLock<BTreeSet<u64>> = OnceLock::new();
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
cargo_hot::connect();
|
||||||
|
|
||||||
|
cargo_hot::subsecond::register_handler(Arc::new(|| {
|
||||||
|
if HOT_FUNCTIONS.get().is_none() {
|
||||||
|
HOT_FUNCTIONS
|
||||||
|
.set(std::mem::take(
|
||||||
|
&mut HOT_FUNCTIONS_PENDING
|
||||||
|
.lock()
|
||||||
|
.expect("Lock hot functions"),
|
||||||
|
))
|
||||||
|
.expect("Set hot functions");
|
||||||
|
}
|
||||||
|
|
||||||
|
IS_STALE.store(false, atomic::Ordering::Relaxed);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call<O>(f: impl FnOnce() -> O) -> O {
|
||||||
|
let mut f = Some(f);
|
||||||
|
|
||||||
|
// The `move` here is important. Hotpatching will not work
|
||||||
|
// otherwise.
|
||||||
|
let mut f = cargo_hot::subsecond::HotFn::current(move || {
|
||||||
|
f.take().expect("Hot function is stale")()
|
||||||
|
});
|
||||||
|
|
||||||
|
let address = f.ptr_address().0;
|
||||||
|
|
||||||
|
if let Some(hot_functions) = HOT_FUNCTIONS.get() {
|
||||||
|
if hot_functions.contains(&address) {
|
||||||
|
IS_STALE.store(true, atomic::Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let _ = HOT_FUNCTIONS_PENDING
|
||||||
|
.lock()
|
||||||
|
.expect("Lock hot functions")
|
||||||
|
.insert(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.call(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_hotpatch(f: impl Fn() + Send + Sync + 'static) {
|
||||||
|
cargo_hot::subsecond::register_handler(Arc::new(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_stale() -> bool {
|
||||||
|
IS_STALE.load(atomic::Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "hot"))]
|
||||||
|
mod hot {
|
||||||
|
pub fn init() {}
|
||||||
|
|
||||||
|
pub fn call<O>(f: impl FnOnce() -> O) -> O {
|
||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue