fix(threading): make auto-reset regression deterministic
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"recorded_unix_seconds": 1786610180,
|
||||
"recorded_unix_seconds": 1786611260,
|
||||
"upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
|
||||
"material_count": 27,
|
||||
"generated_output_count": 8,
|
||||
@@ -12,7 +12,7 @@
|
||||
"dependency_manifest_sha256": "5f80b45ab18a45365673b55b52d68318bc31f602ce2f6559f573027cc446c58e",
|
||||
"third_party_notices_sha256": "c4d381944a9b57277963d2a5ee4e23a9a064c2ba93a676a49e023931b53a71d6",
|
||||
"native_notices_sha256": "b417ee7bf6b748cc86839e5354753c0f8c1f8309d13c0fea379c77f602e69fc0",
|
||||
"distribution_manifest_sha256": "9dc77128962f410e5ff7ecee947d2726e537cc42d9ef57a18d639c9bdcd2406e",
|
||||
"distribution_manifest_sha256": "95af81f60a3823cac35e6716d1500d052bc7e22127d84f705798414a085f6762",
|
||||
"unknown_materials": 0,
|
||||
"unknown_bundled_assets": 0,
|
||||
"status": "ok"
|
||||
|
||||
@@ -913,34 +913,50 @@ impl WaitHandleAsyncFactory {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Barrier, mpsc};
|
||||
|
||||
#[test]
|
||||
fn auto_reset_releases_exactly_one_waiter_per_signal() {
|
||||
for _ in 0..32 {
|
||||
let event = Arc::new(ManagedAutoResetEvent::new_with_constructor().unwrap());
|
||||
let first = Arc::clone(&event);
|
||||
let second = Arc::clone(&event);
|
||||
let first_done = Arc::new(AtomicBool::new(false));
|
||||
let second_done = Arc::new(AtomicBool::new(false));
|
||||
let first_flag = Arc::clone(&first_done);
|
||||
let second_flag = Arc::clone(&second_done);
|
||||
let a = std::thread::spawn(move || {
|
||||
first.wait_one_with_method().unwrap();
|
||||
first_flag.store(true, Ordering::SeqCst);
|
||||
});
|
||||
let b = std::thread::spawn(move || {
|
||||
second.wait_one_with_method().unwrap();
|
||||
second_flag.store(true, Ordering::SeqCst);
|
||||
});
|
||||
std::thread::sleep(Duration::from_millis(20));
|
||||
let ready = Arc::new(Barrier::new(3));
|
||||
let (completed, completions) = mpsc::channel();
|
||||
let mut waiters = Vec::new();
|
||||
for id in 0..2 {
|
||||
let event = Arc::clone(&event);
|
||||
let ready = Arc::clone(&ready);
|
||||
let completed = completed.clone();
|
||||
waiters.push(std::thread::spawn(move || {
|
||||
ready.wait();
|
||||
event.wait_one_with_method().unwrap();
|
||||
completed.send(id).unwrap();
|
||||
}));
|
||||
}
|
||||
drop(completed);
|
||||
|
||||
// Release both contenders together. The signal is deliberately
|
||||
// allowed to race their actual wait calls: an auto-reset event
|
||||
// must retain one signal even when no waiter has blocked yet.
|
||||
ready.wait();
|
||||
event.set().unwrap();
|
||||
std::thread::sleep(Duration::from_millis(20));
|
||||
assert_ne!(
|
||||
first_done.load(Ordering::SeqCst),
|
||||
second_done.load(Ordering::SeqCst)
|
||||
let first = completions
|
||||
.recv_timeout(Duration::from_secs(2))
|
||||
.expect("one waiter must consume the first signal");
|
||||
assert_eq!(
|
||||
completions.recv_timeout(Duration::from_millis(10)),
|
||||
Err(mpsc::RecvTimeoutError::Timeout),
|
||||
"one auto-reset signal released both waiters"
|
||||
);
|
||||
|
||||
event.set().unwrap();
|
||||
a.join().unwrap();
|
||||
b.join().unwrap();
|
||||
let second = completions
|
||||
.recv_timeout(Duration::from_secs(2))
|
||||
.expect("the second waiter must consume the second signal");
|
||||
assert_ne!(first, second);
|
||||
for waiter in waiters {
|
||||
waiter.join().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1547,8 +1547,8 @@
|
||||
},
|
||||
{
|
||||
"path": "crates/libremetaverse/src/threading_runtime.rs",
|
||||
"bytes": 30843,
|
||||
"sha256": "2ab324af0ba240770e7fd0a6d12d3fc4e6972722d099d9e7914e11cac18bef0e"
|
||||
"bytes": 31537,
|
||||
"sha256": "f08e8055e56655e922b4806f13f003ea0cd3574ad9fb8bdac5d11e1697fc51ab"
|
||||
},
|
||||
{
|
||||
"path": "crates/libremetaverse/src/transfers.rs",
|
||||
|
||||
Reference in New Issue
Block a user