weak_static/lib.rs
1//! This crate provides a macro to create a static value that gets created when needed
2//! and dropped as soon as its not needed anymore.
3//! It requires the `lazy_static` macro to be imported.
4//!
5//! # Example
6//!
7//! ```rust
8//! #[macro_use] extern crate lazy_static;
9//! #[macro_use] extern crate weak_static;
10//!
11//! struct Foo;
12//!
13//! impl Foo {
14//! fn new() -> Self {
15//! println!("new");
16//! Foo
17//! }
18//! }
19//!
20//! impl Drop for Foo {
21//! fn drop(&mut self) {
22//! println!("drop");
23//! }
24//! }
25//!
26//! weak_static! {
27//! static FOO: Foo = Foo::new();
28//! }
29//!
30//! fn main() {
31//! {
32//! let _foo1 = FOO();
33//! let _foo2 = FOO();
34//! let _foo3 = FOO();
35//! }
36//!
37//! {
38//! let _foo4 = FOO();
39//! let _foo5 = FOO();
40//! let _foo6 = FOO();
41//! }
42//! }
43//! ```
44//!
45//! Outputs:
46//!
47//! ```text
48//! new
49//! drop
50//! new
51//! drop
52//! ```
53//!
54//! The `new` prints corresponds to the `FOO()` calls of `_foo1` and `_foo4`.
55//! The `drop` prints correspond to the last FOO reference being dropped.
56//!
57
58#[macro_export]
59macro_rules! weak_static {
60 (static $ident:ident : $typ:ty = $init:expr; ) => (
61 #[allow(non_snake_case)]
62 fn $ident() -> ::std::sync::Arc<$typ> {
63 #[warn(non_snake_case)]
64 {
65 lazy_static! {
66 static ref VALUE: ::std::sync::Mutex<::std::sync::Weak<$typ>> =
67 ::std::default::Default::default();
68 }
69
70 let mut value = VALUE.lock().unwrap();
71
72 value.upgrade().unwrap_or_else(|| {
73 let new_value = ::std::sync::Arc::new($init);
74
75 *value = ::std::sync::Arc::downgrade(&new_value);
76
77 new_value
78 })
79 }
80 }
81 )
82}