diff options
Diffstat (limited to 'devices/src/usb/xhci/ring_buffer_stop_cb.rs')
-rw-r--r-- | devices/src/usb/xhci/ring_buffer_stop_cb.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/devices/src/usb/xhci/ring_buffer_stop_cb.rs b/devices/src/usb/xhci/ring_buffer_stop_cb.rs new file mode 100644 index 0000000..29b3aa1 --- /dev/null +++ b/devices/src/usb/xhci/ring_buffer_stop_cb.rs @@ -0,0 +1,56 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use std::sync::{Arc, Mutex}; + +/// RingBufferStopCallback wraps a callback. The callback will be invoked when last instance of +/// RingBufferStopCallback and its clones is dropped. +/// +/// The callback might not be invoked in certain cases. Don't depend this for safety. +#[derive(Clone)] +pub struct RingBufferStopCallback { + inner: Arc<Mutex<RingBufferStopCallbackInner>>, +} + +impl RingBufferStopCallback { + /// Create new callback from closure. + pub fn new<C: 'static + FnMut() + Send>(cb: C) -> RingBufferStopCallback { + RingBufferStopCallback { + inner: Arc::new(Mutex::new(RingBufferStopCallbackInner { + callback: Box::new(cb), + })), + } + } +} + +struct RingBufferStopCallbackInner { + callback: Box<FnMut() + Send>, +} + +impl Drop for RingBufferStopCallbackInner { + fn drop(&mut self) { + (self.callback)(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::{Arc, Mutex}; + + fn task(_: RingBufferStopCallback) {} + + #[test] + fn simple_raii_callback() { + let a = Arc::new(Mutex::new(0)); + let ac = a.clone(); + let cb = RingBufferStopCallback::new(move || { + *ac.lock().unwrap() = 1; + }); + task(cb.clone()); + task(cb.clone()); + task(cb); + assert_eq!(*a.lock().unwrap(), 1); + } +} |