run_down/
lib.rs

1// Copyright 2019 Brian Gianforcaro
2
3//! Run-down protection as a pattern is useful in situations where re-initialization
4//! or destruction of a shared resource is required in a [SMP][smp-link] environment.
5//! The pattern has two parts, a means to guarantee the resource is accessible and remains so for
6//! the during of it's usage. As well as way to make the resource inaccessible from a point going forward
7//! and the ability to wait for all outstanding usages to drain so you can safely perform the required operation.
8//!
9//! This crate was inspired by the [run-down protection primitive in the NT kernel][nt-run-down-docs].
10//! Where it's used in situations such as driver unload, where futher access to the driver
11//! needs to be rejected and the unloading thread must wait for inflight acesss to stop before
12//! the driver can be completely unload.
13//!
14//! # Example
15//!
16//! ```rust
17//! use run_down::{
18//!     RundownGuard,
19//!     RundownRef
20//! };
21//! use std::sync::Arc;
22//! use std::thread;
23//! use std::time::Duration;
24//!
25//! let rundown = Arc::new(RundownRef::new());
26//!
27//! for i in 1..25 {
28//!
29//!     let rundown_clone = Arc::clone(&rundown);
30//!
31//!     thread::spawn(move || {
32//!
33//!         // Attempt to acquire rundown protection, while the main
34//!         // thread could be running down the object as we execute.
35//!         //
36//!         match rundown_clone.try_acquire() {
37//!             Ok(run_down_guard) => {
38//!                 println!("{}: Run-down protection acquired.", i);
39//!
40//!                 // Stall the thread while holding rundown protection.
41//!                 thread::sleep(Duration::from_millis(10));
42//!             }
43//!             Err(m) => {
44//!                 println!("{}: Failed to acquire run-down protection - {:?}", i, m);
45//!             },
46//!         }
47//!     });
48//! }
49//!
50//! println!("0: Waiting for rundown to complete");
51//! rundown.wait_for_rundown();
52//! println!("0: Rundown complete");
53//! ```
54//!
55//! [nt-run-down-docs]: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/run-down-protection
56//! [smp-link]: https://en.wikipedia.org/wiki/Symmetric_multiprocessing
57
58// Subscribe to most of the clippy lints.
59#![warn(
60    clippy::all,
61    clippy::restriction,
62    clippy::pedantic,
63    clippy::nursery,
64    clippy::cargo
65)]
66// Disable warnings for things we don't care about.
67#![allow(unknown_lints)]
68#![allow(clippy::implicit_return)]
69#![allow(clippy::missing_inline_in_public_items)]
70#![allow(clippy::multiple_inherent_impl)]
71#![allow(clippy::multiple_crate_versions)]
72#![allow(clippy::module_name_repetitions)]
73#![allow(clippy::missing_docs_in_private_items)]
74
75// Import the crates we need to use
76#[macro_use]
77extern crate bitflags;
78extern crate lazy_init;
79extern crate rsevents;
80
81mod flags;
82mod guard;
83mod rundown_ref;
84pub use guard::RundownGuard;
85pub use rundown_ref::RundownError;
86pub use rundown_ref::RundownRef;
87
88extern crate doc_comment;
89
90// Test examples in the README file.
91doc_comment::doctest!("../README.md", readme_examples);