Skip to main content

fxfs/
test_callback.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use fuchsia_sync::Mutex;
6use std::sync::Arc;
7
8pub struct TestCallback(Mutex<Option<Arc<dyn Fn() + Send + Sync>>>);
9pub struct TestCallbackGuard(&'static TestCallback);
10
11impl Drop for TestCallbackGuard {
12    fn drop(&mut self) {
13        *self.0.0.lock() = None;
14    }
15}
16
17impl TestCallback {
18    pub const fn new() -> Self {
19        Self(Mutex::new(None))
20    }
21
22    /// Returns a guard that invalidates this callback and releases the resources when dropped.
23    pub fn set<F>(&'static self, callback: F) -> TestCallbackGuard
24    where
25        F: Fn() + Send + Sync + 'static,
26    {
27        let arc: Arc<dyn Fn() + Send + Sync> = Arc::new(callback);
28        {
29            let mut inner = self.0.lock();
30            assert!(inner.is_none(), "Resetting TestCallback without dropping old guard.");
31            *inner = Some(arc.clone());
32        }
33        TestCallbackGuard(&self)
34    }
35
36    pub fn call(&self) {
37        let cb = self.0.lock().as_ref().map(|cb| cb.clone());
38        // Call the callback outside the lock. This isn't really a race though, since just calling
39        // the callback doesn't ensure that any action will actually be done inside it, and this
40        // delay to calling the callback is impossible to differentiate from that delay.
41        if let Some(cb) = cb {
42            cb();
43        }
44    }
45}