Compare commits

...

6 Commits

Author SHA1 Message Date
Aaron Fenyes
a5fd6545e0 Remove caveat about NEXT_ELEMENT_SERIAL wrapping
Commit 133b725 should make it impossible for the serial numbers to wrap.
2024-11-21 16:47:45 -08:00
Aaron Fenyes
133b725053 Panic if we run out of serial numbers 2024-11-21 16:42:43 -08:00
Aaron Fenyes
c5f09b99b3 Add reminder to reconsider global element serials 2024-11-21 16:03:58 -08:00
Aaron Fenyes
b0bd31a9da Go back to atomic for next element serial number
This reverts commit 7bc3a9eeae.

I'd hoped that `thread_local!` would force our code to be single-
threaded, but apparently it doesn't. With a global mutable static, it
seems like we have to include some kind of thread-safety to avoid
`unsafe` code, and an atomic provides the kind of safety we actually
want.
2024-11-21 15:55:40 -08:00
Aaron Fenyes
7bc3a9eeae Make the next element serial number thread-local
In the last revision, the next element serial number was thread-safe,
but that might be overdoing it. I suspect that elements will only ever
be created from the main thread.
2024-11-18 20:29:53 -08:00
Aaron Fenyes
6b2d44a58c Assign each element a serial number
For future thread-safety, keep the next serial number in a static atomic
variable.
2024-11-18 16:08:06 -08:00
2 changed files with 25 additions and 2 deletions

View File

@ -1,7 +1,7 @@
use nalgebra::{DMatrix, DVector}; use nalgebra::{DMatrix, DVector};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use slab::Slab; use slab::Slab;
use std::collections::BTreeSet; use std::{collections::BTreeSet, sync::atomic::{AtomicU64, Ordering}};
use sycamore::prelude::*; use sycamore::prelude::*;
use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */ use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */
@ -13,6 +13,13 @@ pub type ConstraintKey = usize;
pub type ElementColor = [f32; 3]; pub type ElementColor = [f32; 3];
/* KLUDGE */
// we should reconsider this design when we build a system for switching between
// assemblies. at that point, we might want to switch to hierarchical keys,
// where each each element has a key that identifies it within its assembly and
// each assembly has a key that identifies it within the sesssion
static NEXT_ELEMENT_SERIAL: AtomicU64 = AtomicU64::new(0);
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct Element { pub struct Element {
pub id: String, pub id: String,
@ -21,6 +28,10 @@ pub struct Element {
pub representation: Signal<DVector<f64>>, pub representation: Signal<DVector<f64>>,
pub constraints: Signal<BTreeSet<ConstraintKey>>, pub constraints: Signal<BTreeSet<ConstraintKey>>,
// a serial number, assigned by `Element::new`, that uniquely identifies
// each element
pub serial: u64,
// the configuration matrix column index that was assigned to this element // the configuration matrix column index that was assigned to this element
// last time the assembly was realized // last time the assembly was realized
column_index: usize column_index: usize
@ -33,12 +44,24 @@ impl Element {
color: ElementColor, color: ElementColor,
representation: DVector<f64> representation: DVector<f64>
) -> Element { ) -> Element {
// take the next serial number, panicking if that was the last number we
// had left. the technique we use to panic on overflow is taken from
// _Rust Atomics and Locks_, by Mara Bos
//
// https://marabos.nl/atomics/atomics.html#example-handle-overflow
//
let serial = NEXT_ELEMENT_SERIAL.fetch_update(
Ordering::SeqCst, Ordering::SeqCst,
|serial| serial.checked_add(1)
).expect("Out of serial numbers for elements");
Element { Element {
id: id, id: id,
label: label, label: label,
color: color, color: color,
representation: create_signal(representation), representation: create_signal(representation),
constraints: create_signal(BTreeSet::default()), constraints: create_signal(BTreeSet::default()),
serial: serial,
column_index: 0 column_index: 0
} }
} }

View File

@ -200,7 +200,7 @@ pub fn Outline() -> View {
view=|(key, elt)| view! { view=|(key, elt)| view! {
ElementOutlineItem(key=key, element=elt) ElementOutlineItem(key=key, element=elt)
}, },
key=|(key, _)| key.clone() key=|(_, elt)| elt.serial
) )
} }
} }