From 6376b1cebf3437aced6449f2f59fb721bda0d48e Mon Sep 17 00:00:00 2001 From: OneSlips Date: Thu, 22 Oct 2026 12:30:30 +1000 Subject: [PATCH 1/5] Issue #136: applying the GPU setting never waits for the device on the UI thread The first frame ran `app.gpu {enabled}` and its reply called `gpu::available()`, which waits for the device that `warm_up` is creating off the UI thread: the window's first frame stalled for the whole device and kernel setup (8-11 s under load). `app.gpu` takes `wait: false`, which answers at once while the device is still being created (available/adapter/reason null), and the UI uses it. `a_slow_photos_import_never_blocks_the_window` caught it (8.8 s -> 0.9 s). Co-Authored-By: Claude Opus 5.5 --- crates/engine/src/cmd/query.rs | 13 ++++++++++++- crates/ui-egui/src/lib.rs | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/cmd/query.rs b/crates/engine/src/cmd/query.rs index dfbf4bfc5..fd81047cd 100644 --- a/crates/engine/src/cmd/query.rs +++ b/crates/engine/src/cmd/query.rs @@ -226,10 +226,21 @@ pub fn specs() -> Vec { "versions": ph.versions.iter().map(|v| json!({"name": v.name, "created": v.created})).collect::>(), })) }), - cmd!(query "app.gpu", "GPU Rendering", [], None, "{enabled?: bool} — allow/forbid GPU rendering (CPU fallback; LIGHTCRAFT_GPU=0 forbids it for the process); returns {enabled, available, adapter, reason (why the GPU is off), lastFallback (latest render redone on the CPU, and why)}", always, |_, p| { + cmd!(query "app.gpu", "GPU Rendering", [], None, "{enabled?: bool, wait?: bool} — allow/forbid GPU rendering (CPU fallback; LIGHTCRAFT_GPU=0 forbids it for the process); returns {enabled, available, adapter, reason (why the GPU is off), lastFallback (latest render redone on the CPU, and why)}. wait: false never waits for a device still being created (available, adapter and reason are then null)", always, |_, p| { if let Some(on) = p.get("enabled").and_then(Value::as_bool) { lightcraft_gpu::set_enabled(on); } + // the UI applies the setting on its first frame: it must not wait seconds for the + // device there (issue #136; `warm_up` creates it off the UI thread) + if p.get("wait").and_then(Value::as_bool) == Some(false) && !lightcraft_gpu::ready() { + return Ok(json!({ + "enabled": lightcraft_gpu::enabled(), + "available": null, + "adapter": null, + "reason": null, + "lastFallback": lightcraft_gpu::last_fallback(), + })); + } Ok(json!({ "enabled": lightcraft_gpu::enabled(), "available": lightcraft_gpu::available(), diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 1b2517907..052aa12c2 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -1263,7 +1263,7 @@ impl LightcraftApp { fn apply_settings(&mut self, ctx: &egui::Context) { if self.gpu_applied != Some(self.ui.settings.gpu) { self.gpu_applied = Some(self.ui.settings.gpu); - let _ = self.session.execute("app.gpu", &serde_json::json!({"enabled": self.ui.settings.gpu})); + let _ = self.session.execute("app.gpu", &serde_json::json!({"enabled": self.ui.settings.gpu, "wait": false})); // GPU device + kernels off the UI thread, once the window is up and only when GPU // rendering is on: a broken driver must not keep the window from appearing (issue #136) if self.ui.settings.gpu { From 32e55afee8d82c8cc5e95e12cd0ba75509a10832 Mon Sep 17 00:00:00 2001 From: OneSlips Date: Sun, 25 Oct 2026 05:15:13 +1000 Subject: [PATCH 2/5] =?UTF-8?q?Issue=20#136:=20app.gpu=20{wait:false}=20st?= =?UTF-8?q?ill=20says=20why=20the=20GPU=20is=20off;=20Settings=20shows=20"?= =?UTF-8?q?GPU:=20starting=E2=80=A6"=20while=20the=20device=20is=20created?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review follow-up: with GPU rendering off (preference, environment, earlier failure) the no-wait reply now reports available=false and the reason at once, without creating the device. The Performance tab no longer calls gpu::available() while the device is still being created, which could block the UI thread. Co-Authored-By: Claude Opus 5.5 --- apps/lightcraft-cli/tests/cli.rs | 19 +++++++++++++------ crates/engine/src/cmd/query.rs | 11 +++++++---- crates/ui-egui/src/panels/settings.rs | 5 ++++- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/apps/lightcraft-cli/tests/cli.rs b/apps/lightcraft-cli/tests/cli.rs index 8f56bafe6..6bdf9e7b9 100644 --- a/apps/lightcraft-cli/tests/cli.rs +++ b/apps/lightcraft-cli/tests/cli.rs @@ -404,7 +404,12 @@ fn snapshot_defaults_to_cpu_without_gpu_environment_overrides() { let script = tmp("default-cpu.jsonl"); std::fs::write( &script, - format!("{}\n{}\n", json!({"method": "engine.execute", "params": {"command": "app.gpu"}}), json!({"method": "ui.screenshot"})), + format!( + "{}\n{}\n{}\n", + json!({"method": "engine.execute", "params": {"command": "app.gpu", "params": {"wait": false}}}), + json!({"method": "engine.execute", "params": {"command": "app.gpu"}}), + json!({"method": "ui.screenshot"}) + ), ) .unwrap(); let image = tmp("default-cpu.png"); @@ -418,11 +423,13 @@ fn snapshot_defaults_to_cpu_without_gpu_environment_overrides() { assert!(output.status.success(), "status {}: {}", output.status, String::from_utf8_lossy(&output.stderr)); let replies: Vec = String::from_utf8_lossy(&output.stdout).lines().map(|line| serde_json::from_str(line).unwrap()).collect(); assert!(replies.iter().all(|reply| reply["ok"] == true), "{replies:?}"); - let gpu = &replies[0]["result"]; - assert_eq!(gpu["enabled"], false, "{gpu}"); - assert_eq!(gpu["available"], false, "{gpu}"); - assert_eq!(gpu["adapter"], Value::Null, "no device is created: {gpu}"); - assert!(gpu["reason"].as_str().is_some_and(|reason| reason.contains("preference")), "{gpu}"); + // `wait: false` (what the UI sends) still says why the GPU is off: no device is being created + for gpu in [&replies[0]["result"], &replies[1]["result"]] { + assert_eq!(gpu["enabled"], false, "{gpu}"); + assert_eq!(gpu["available"], false, "{gpu}"); + assert_eq!(gpu["adapter"], Value::Null, "no device is created: {gpu}"); + assert!(gpu["reason"].as_str().is_some_and(|reason| reason.contains("preference")), "{gpu}"); + } let decoded = lightcraft_codecs::decode(&std::fs::read(image).unwrap(), Default::default()).unwrap(); assert_eq!((decoded.width, decoded.height), (480, 320)); } diff --git a/crates/engine/src/cmd/query.rs b/crates/engine/src/cmd/query.rs index fd81047cd..52dca09ed 100644 --- a/crates/engine/src/cmd/query.rs +++ b/crates/engine/src/cmd/query.rs @@ -226,18 +226,21 @@ pub fn specs() -> Vec { "versions": ph.versions.iter().map(|v| json!({"name": v.name, "created": v.created})).collect::>(), })) }), - cmd!(query "app.gpu", "GPU Rendering", [], None, "{enabled?: bool, wait?: bool} — allow/forbid GPU rendering (CPU fallback; LIGHTCRAFT_GPU=0 forbids it for the process); returns {enabled, available, adapter, reason (why the GPU is off), lastFallback (latest render redone on the CPU, and why)}. wait: false never waits for a device still being created (available, adapter and reason are then null)", always, |_, p| { + cmd!(query "app.gpu", "GPU Rendering", [], None, "{enabled?: bool, wait?: bool} — allow/forbid GPU rendering (CPU fallback; LIGHTCRAFT_GPU=0 forbids it for the process); returns {enabled, available, adapter, reason (why the GPU is off), lastFallback (latest render redone on the CPU, and why)}. wait: false never waits for a device still being created (available, adapter and reason are then null; with GPU rendering off they say so at once)", always, |_, p| { if let Some(on) = p.get("enabled").and_then(Value::as_bool) { lightcraft_gpu::set_enabled(on); } // the UI applies the setting on its first frame: it must not wait seconds for the // device there (issue #136; `warm_up` creates it off the UI thread) if p.get("wait").and_then(Value::as_bool) == Some(false) && !lightcraft_gpu::ready() { + // off (preference, environment): known at once, and asking the adapter would + // create the device; on: still being created, so nothing is known yet + let on = lightcraft_gpu::enabled(); return Ok(json!({ - "enabled": lightcraft_gpu::enabled(), - "available": null, + "enabled": on, + "available": if on { Value::Null } else { Value::Bool(false) }, "adapter": null, - "reason": null, + "reason": if on { None } else { lightcraft_gpu::unavailable_reason() }, "lastFallback": lightcraft_gpu::last_fallback(), })); } diff --git a/crates/ui-egui/src/panels/settings.rs b/crates/ui-egui/src/panels/settings.rs index 2f844f4ae..8debaeeaf 100644 --- a/crates/ui-egui/src/panels/settings.rs +++ b/crates/ui-egui/src/panels/settings.rs @@ -417,7 +417,10 @@ fn performance_tab(app: &mut LightcraftApp, ui: &mut egui::Ui, t: &Tokens) { use lightcraft_engine::gpu; heading(ui, t, crate::i18n::tr("Rendering")); check(ui, "settings.gpu", &mut app.ui.settings.gpu, "Use the GPU for rendering"); - let status = if !gpu::available() { + // `available` would wait for a device still being created (issue #136) + let status = if gpu::enabled() && !gpu::ready() { + "GPU: starting…".to_string() + } else if !gpu::available() { match gpu::unavailable_reason() { Some(why) => crate::i18n::tr_format!("Rendering on the CPU: {why}", why = why), None => "No usable GPU found: rendering on the CPU".to_string(), From 9a6ac9aea7ead542f63173ef894fc824099f91d7 Mon Sep 17 00:00:00 2001 From: OneSlips Date: Sun, 25 Oct 2026 13:48:25 +1000 Subject: [PATCH 3/5] Issue #136: a non-waiting GPU query starts the device; Settings repaints while it starts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `app.gpu {wait: false}` with GPU rendering on starts creating the device in the background (`warm_up`), so a caller that never waits still gets an answer later. `warm_up` starts one thread at most, and may start again if GPU rendering was turned off before it ran. - Settings > Performance asks for a repaint every 250 ms while it shows "GPU: starting…": the device is created on another thread, which doesn't wake the window. - CLI test: `{enabled: true, wait: false}` answers enabled with available, adapter and reason null (skips with LIGHTCRAFT_GPU=0, since it starts creating a device). Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 1 + apps/lightcraft-cli/Cargo.toml | 3 +++ apps/lightcraft-cli/tests/it/cli.rs | 35 +++++++++++++++++++++++++++ crates/engine/src/cmd/query.rs | 7 +++++- crates/gpu/src/lib.rs | 15 ++++++++++-- crates/ui-egui/src/panels/settings.rs | 2 ++ 6 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78de058c3..60b893afe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3141,6 +3141,7 @@ dependencies = [ "lightcraft-merge", "lightcraft-raster", "lightcraft-sysmem", + "lightcraft-testkit", "lightcraft-ui-egui", "serde_json", ] diff --git a/apps/lightcraft-cli/Cargo.toml b/apps/lightcraft-cli/Cargo.toml index b82aca1d5..e55d458b3 100644 --- a/apps/lightcraft-cli/Cargo.toml +++ b/apps/lightcraft-cli/Cargo.toml @@ -25,6 +25,9 @@ lightcraft-merge = { workspace = true } serde_json = { workspace = true } dhat = { workspace = true, optional = true } +[dev-dependencies] +lightcraft-testkit = { workspace = true } + [features] default = ["denoise"] denoise = ["lightcraft-engine/denoise"] diff --git a/apps/lightcraft-cli/tests/it/cli.rs b/apps/lightcraft-cli/tests/it/cli.rs index 78ee42561..4ea499cf1 100644 --- a/apps/lightcraft-cli/tests/it/cli.rs +++ b/apps/lightcraft-cli/tests/it/cli.rs @@ -466,6 +466,41 @@ fn snapshot_defaults_to_cpu_without_gpu_environment_overrides() { assert_eq!((decoded.width, decoded.height), (480, 320)); } +/// Issue #136: `app.gpu {enabled: true, wait: false}` (what the UI sends on its first frame) answers +/// at once while the device is still being created: enabled, and nothing known yet (`null`), instead +/// of waiting for the driver. It starts creating the device (off the calling thread), so this test +/// touches the GPU driver and skips when the environment turns the GPU off. +#[test] +fn enabling_the_gpu_without_waiting_answers_before_the_device_exists() { + if std::env::var("LIGHTCRAFT_GPU").is_ok_and(|v| matches!(v.trim(), "0" | "off" | "false" | "no")) { + lightcraft_testkit::skip!(Gpu, "LIGHTCRAFT_GPU=0: enabling the GPU starts creating a device"); + return; + } + let script = tmp("gpu-starting.jsonl"); + std::fs::write( + &script, + format!("{}\n", json!({"method": "engine.execute", "params": {"command": "app.gpu", "params": {"enabled": true, "wait": false}}})), + ) + .unwrap(); + let image = tmp("gpu-starting.png"); + let output = Command::new(BIN) + .env_remove("LIGHTCRAFT_GPU") + .env_remove("LIGHTCRAFT_GPU_BACKEND") + .env_remove("WGPU_BACKEND") + .args(["snapshot", "--demo", "--script", script.to_str().unwrap(), "-o", image.to_str().unwrap(), "--size", "480x320"]) + .output() + .unwrap(); + assert!(output.status.success(), "status {}: {}", output.status, String::from_utf8_lossy(&output.stderr)); + let replies: Vec = String::from_utf8_lossy(&output.stdout).lines().map(|line| serde_json::from_str(line).unwrap()).collect(); + assert_eq!(replies.len(), 1, "{replies:?}"); + assert_eq!(replies[0]["ok"], true, "{replies:?}"); + let gpu = &replies[0]["result"]; + assert_eq!(gpu["enabled"], true, "{gpu}"); + for field in ["available", "adapter", "reason"] { + assert_eq!(gpu[field], Value::Null, "{field} is not known while the device is created: {gpu}"); + } +} + /// Issue #136: with the GPU switched off from the environment the UI starts and renders on the CPU, /// without creating a GPU device (no driver is loaded), and says why. #[test] diff --git a/crates/engine/src/cmd/query.rs b/crates/engine/src/cmd/query.rs index b50bc72a1..469253805 100644 --- a/crates/engine/src/cmd/query.rs +++ b/crates/engine/src/cmd/query.rs @@ -230,7 +230,7 @@ pub fn specs() -> Vec { "versions": ph.versions.iter().map(|v| json!({"name": v.name, "created": v.created})).collect::>(), })) }), - cmd!(query "app.gpu", "GPU Rendering", [], None, "{enabled?: bool, wait?: bool} — allow/forbid GPU rendering (CPU fallback; LIGHTCRAFT_GPU=0 forbids it for the process); returns {enabled, available, adapter, reason (why the GPU is off), lastFallback (latest render redone on the CPU, and why)}. wait: false never waits for a device still being created (available, adapter and reason are then null; with GPU rendering off they say so at once)", always, |_, p| { + cmd!(query "app.gpu", "GPU Rendering", [], None, "{enabled?: bool, wait?: bool} — allow/forbid GPU rendering (CPU fallback; LIGHTCRAFT_GPU=0 forbids it for the process); returns {enabled, available, adapter, reason (why the GPU is off), lastFallback (latest render redone on the CPU, and why)}. wait: false never waits for a device still being created (available, adapter and reason are then null and the device is created in the background; with GPU rendering off they say so at once)", always, |_, p| { if let Some(on) = p.get("enabled").and_then(Value::as_bool) { lightcraft_gpu::set_enabled(on); } @@ -240,6 +240,11 @@ pub fn specs() -> Vec { // off (preference, environment): known at once, and asking the adapter would // create the device; on: still being created, so nothing is known yet let on = lightcraft_gpu::enabled(); + if on { + // a caller that never waits still gets an answer later (off the UI thread; + // starts at most once) + lightcraft_gpu::warm_up(); + } return Ok(json!({ "enabled": on, "available": if on { Value::Null } else { Value::Bool(false) }, diff --git a/crates/gpu/src/lib.rs b/crates/gpu/src/lib.rs index 452e2dd67..58aa1d967 100644 --- a/crates/gpu/src/lib.rs +++ b/crates/gpu/src/lib.rs @@ -308,13 +308,24 @@ pub(crate) fn existing_device() -> Option<&'static ctx::Gpu> { /// Create the device and compile the kernels on a background thread now (once the window is up), /// so the first render doesn't wait ~0.3–0.4 s for it and the UI thread never does. Does nothing -/// while GPU rendering is turned off. +/// while GPU rendering is turned off. Repeated calls start one thread at most. pub fn warm_up() { #[cfg(not(target_arch = "wasm32"))] if !env_disabled() && ENABLED.load(Ordering::Relaxed) && GPU.get().is_none() { - let _ = std::thread::Builder::new().name("lc-gpu-init".into()).spawn(|| { + static STARTED: AtomicBool = AtomicBool::new(false); + if STARTED.swap(true, Ordering::AcqRel) { + return; + } + let spawned = std::thread::Builder::new().name("lc-gpu-init".into()).spawn(|| { let _ = device(); + // turned off before the thread ran (nothing created): a later call may start again + if GPU.get().is_none() { + STARTED.store(false, Ordering::Release); + } }); + if spawned.is_err() { + STARTED.store(false, Ordering::Release); + } } } diff --git a/crates/ui-egui/src/panels/settings.rs b/crates/ui-egui/src/panels/settings.rs index 95d09c306..555aa349c 100644 --- a/crates/ui-egui/src/panels/settings.rs +++ b/crates/ui-egui/src/panels/settings.rs @@ -588,6 +588,8 @@ fn performance_tab(app: &mut LightcraftApp, ui: &mut egui::Ui, t: &Tokens) { check(ui, "settings.gpu", &mut app.ui.settings.gpu, "Use the GPU for rendering"); // `available` would wait for a device still being created (issue #136) let status = if gpu::enabled() && !gpu::ready() { + // the device is created on another thread, which doesn't wake the UI when it's done + ui.ctx().request_repaint_after(std::time::Duration::from_millis(250)); "GPU: starting…".to_string() } else if !gpu::available() { match gpu::unavailable_reason() { From 8541131cd8464d1948144c44718f8c824f04d56c Mon Sep 17 00:00:00 2001 From: OneSlips Date: Sun, 25 Oct 2026 18:58:20 +1000 Subject: [PATCH 4/5] Issue #136: a GPU start lost to an off/on switch is retried MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by radialmonster: turned off before `lc-gpu-init` created the device and back on, `warm_up` saw the start still held and returned, then the thread released it with no device, leaving Settings > Performance at "GPU: starting…". The thread now releases the flag first, then reads the preference again and tries again itself when GPU rendering is back on (it stops when another start took over, at shutdown or with the environment's off switch). Settings > Performance also calls the idempotent `gpu::warm_up()` in its "starting" branch (their suggestion), on the repaint it already asks for. Co-Authored-By: Claude Opus 5.5 --- crates/gpu/src/lib.rs | 17 +++++++++++++---- crates/ui-egui/src/panels/settings.rs | 5 ++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/gpu/src/lib.rs b/crates/gpu/src/lib.rs index 58aa1d967..84aad52ea 100644 --- a/crates/gpu/src/lib.rs +++ b/crates/gpu/src/lib.rs @@ -317,10 +317,19 @@ pub fn warm_up() { return; } let spawned = std::thread::Builder::new().name("lc-gpu-init".into()).spawn(|| { - let _ = device(); - // turned off before the thread ran (nothing created): a later call may start again - if GPU.get().is_none() { - STARTED.store(false, Ordering::Release); + loop { + let _ = device(); + if GPU.get().is_some() || shutting_down() || env_disabled() { + break; + } + // turned off before the thread ran (nothing created): a later call may start + // again. Released first, then the preference read again: a call made while this + // thread still held the flag (turned back on meanwhile) returned without starting + // one, so this thread tries again itself rather than leave "starting" for good. + STARTED.store(false, Ordering::SeqCst); + if !ENABLED.load(Ordering::SeqCst) || STARTED.swap(true, Ordering::SeqCst) { + break; + } } }); if spawned.is_err() { diff --git a/crates/ui-egui/src/panels/settings.rs b/crates/ui-egui/src/panels/settings.rs index 555aa349c..111b37a28 100644 --- a/crates/ui-egui/src/panels/settings.rs +++ b/crates/ui-egui/src/panels/settings.rs @@ -588,7 +588,10 @@ fn performance_tab(app: &mut LightcraftApp, ui: &mut egui::Ui, t: &Tokens) { check(ui, "settings.gpu", &mut app.ui.settings.gpu, "Use the GPU for rendering"); // `available` would wait for a device still being created (issue #136) let status = if gpu::enabled() && !gpu::ready() { - // the device is created on another thread, which doesn't wake the UI when it's done + // the device is created on another thread, which doesn't wake the UI when it's done; + // make sure that thread runs (cheap and idempotent: a start lost to an off/on switch + // can't leave "starting" for good) + gpu::warm_up(); ui.ctx().request_repaint_after(std::time::Duration::from_millis(250)); "GPU: starting…".to_string() } else if !gpu::available() { From caba780e1e97c189dd8750712a6891847760d7c6 Mon Sep 17 00:00:00 2001 From: OneSlips Date: Sun, 25 Oct 2026 21:00:50 +1000 Subject: [PATCH 5/5] Issue #136: the GPU preference and the warm-up flag use one ordering set_enabled now stores the preference with SeqCst, as the warm-up thread reads it after releasing its start, so a switch back on made meanwhile is always seen there (CodeRabbit). The start flag uses SeqCst throughout. Co-Authored-By: Claude Opus 5.5 --- crates/gpu/src/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/gpu/src/lib.rs b/crates/gpu/src/lib.rs index 84aad52ea..e66a8fadd 100644 --- a/crates/gpu/src/lib.rs +++ b/crates/gpu/src/lib.rs @@ -193,7 +193,9 @@ pub fn reset_failures() { /// Allow or forbid GPU rendering at runtime (a preference). `LIGHTCRAFT_GPU=0` forbids it for the /// whole process regardless. pub fn set_enabled(on: bool) { - ENABLED.store(on, Ordering::Relaxed); + // (SeqCst, as `warm_up`'s thread reads it after releasing its start: a switch back on is + // never missed there) + ENABLED.store(on, Ordering::SeqCst); } /// Whether GPU rendering is allowed (environment, preference, no earlier failure — real, or @@ -311,9 +313,9 @@ pub(crate) fn existing_device() -> Option<&'static ctx::Gpu> { /// while GPU rendering is turned off. Repeated calls start one thread at most. pub fn warm_up() { #[cfg(not(target_arch = "wasm32"))] - if !env_disabled() && ENABLED.load(Ordering::Relaxed) && GPU.get().is_none() { + if !env_disabled() && ENABLED.load(Ordering::SeqCst) && GPU.get().is_none() { static STARTED: AtomicBool = AtomicBool::new(false); - if STARTED.swap(true, Ordering::AcqRel) { + if STARTED.swap(true, Ordering::SeqCst) { return; } let spawned = std::thread::Builder::new().name("lc-gpu-init".into()).spawn(|| { @@ -333,7 +335,7 @@ pub fn warm_up() { } }); if spawned.is_err() { - STARTED.store(false, Ordering::Release); + STARTED.store(false, Ordering::SeqCst); } } }