diff --git a/master/lazy_static/fn.initialize.html b/master/lazy_static/fn.initialize.html index 852d907ae..e05c03ad3 100644 --- a/master/lazy_static/fn.initialize.html +++ b/master/lazy_static/fn.initialize.html @@ -59,7 +59,7 @@ [−] - [src] + [src]
pub fn initialize<T: LazyStatic>(lazy: &T)
Takes a shared reference to a lazy static and initializes it if it has not been already.
This can be used to control the initialization point of a lazy static.
diff --git a/master/lazy_static/index.html b/master/lazy_static/index.html index d0f8aa78c..2b3458fc9 100644 --- a/master/lazy_static/index.html +++ b/master/lazy_static/index.html @@ -33,7 +33,7 @@A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have statics that require code to be
executed at runtime in order to be initialized.
@@ -73,15 +73,26 @@ as well as anything that requires function calls to be computed.
Metadata (such as doc comments) is allowed on each ref.
-Attributes (including doc comments) are supported as well:
+ ++lazy_static! { + /// This is an example for using doc comment attributes + static ref EXAMPLE: u8 = 42; +}+
For a given static ref NAME: TYPE = EXPR;, the macro generates a unique type that
-implements Deref<TYPE> and stores it in a static with name NAME. (Metadata ends up
+implements Deref<TYPE> and stores it in a static with name NAME. (Attributes end up
attaching to this type.)
On first deref, EXPR gets evaluated and stored internally, such that all further derefs
-can return a reference to the same object.
Like regular static muts, this macro only works for types that fulfill the Sync
-trait.
Apart from the lazy initialization, the resulting "static ref" variables +have generally the same properties as regular "static" variables:
+Sync trait.Using the macro:
@@ -114,11 +125,37 @@ trait.The Deref implementation uses a hidden static variable that is guarded by a atomic check on each access. On stable Rust, the macro may need to allocate each static on the heap.
| __lazy_static_create | ++ + | +
| lazy_static | + | +
| LazyStatic | +
+ Support trait for enabling a few common operation on lazy static values. + + |
+
| initialize | +
+ Takes a shared reference to a lazy static and initializes +it if it has not been already. + |
macro_rules! lazy_static { ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { ... }; ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { ... }; - ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { ... }; - (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => { ... }; - (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => { ... }; + ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { ... }; () => { ... }; }diff --git a/master/lazy_static/sidebar-items.js b/master/lazy_static/sidebar-items.js index a31c45a27..4d5142dd5 100644 --- a/master/lazy_static/sidebar-items.js +++ b/master/lazy_static/sidebar-items.js @@ -1 +1 @@ -initSidebarItems({"macro":[["lazy_static",""]]}); \ No newline at end of file +initSidebarItems({"fn":[["initialize","Takes a shared reference to a lazy static and initializes it if it has not been already."]],"macro":[["__lazy_static_create",""],["lazy_static",""]],"trait":[["LazyStatic","Support trait for enabling a few common operation on lazy static values."]]}); \ No newline at end of file diff --git a/master/lazy_static/trait.LazyStatic.html b/master/lazy_static/trait.LazyStatic.html index af2cef1cd..eaa03767e 100644 --- a/master/lazy_static/trait.LazyStatic.html +++ b/master/lazy_static/trait.LazyStatic.html @@ -59,7 +59,7 @@ [−] - [src] + [src]
pub trait LazyStatic { }Support trait for enabling a few common operation on lazy static values.
This is implemented by each defined lazy static, and used by the free functions in this crate.
diff --git a/master/search-index.js b/master/search-index.js index d160fd945..1ef04b7b3 100644 --- a/master/search-index.js +++ b/master/search-index.js @@ -23,7 +23,7 @@ searchIndex["futures_cpupool"] = {"doc":"A simple crate for executing work on a searchIndex["itertools"] = {"doc":"Itertools — extra iterator adaptors, functions and macros.","items":[[4,"Either","itertools","The enum `Either` with variants `Left` and `Right` is a general purpose sum type with two cases.",null,null],[13,"Left","","A value of type `L`.",0,null],[13,"Right","","A value of type `R`.",0,null],[4,"Diff","","A type returned by the `diff_with` function.",null,null],[13,"FirstMismatch","","The index of the first non-matching element along with both iterator's remaining elements starting with the first mis-match.",1,null],[13,"Shorter","","The total number of elements that were in `J` along with the remaining elements of `I`.",1,null],[13,"Longer","","The total number of elements that were in `I` along with the remaining elements of `J`.",1,null],[4,"MinMaxResult","","`MinMaxResult` is an enum returned by `minmax`. See `Itertools::minmax()` for more detail.",null,null],[13,"NoElements","","Empty iterator",2,null],[13,"OneElement","","Iterator with one element, so the minimum and maximum are the same",2,null],[13,"MinMax","","More than one element in the iterator, the first element is not larger than the second",2,null],[4,"Position","","A value yielded by `WithPosition`. Indicates the position of this element in the iterator results.",null,null],[13,"First","","This is the first element.",3,null],[13,"Middle","","This is neither the first nor the last element.",3,null],[13,"Last","","This is the last element.",3,null],[13,"Only","","This is the only element.",3,null],[4,"EitherOrBoth","","A value yielded by `ZipLongest`. Contains one or two values, depending on which of the input iterators are exhausted.",null,null],[13,"Both","","Neither input iterator is exhausted yet, yielding two values.",4,null],[13,"Left","","The parameter iterator of `.zip_longest()` is exhausted, only yielding a value from the `self` iterator.",4,null],[13,"Right","","The `self` iterator of `.zip_longest()` is exhausted, only yielding a value from the parameter iterator.",4,null],[4,"FoldWhile","","An enum used for controlling the execution of `.fold_while()`.",null,null],[13,"Continue","","Continue folding with this value",5,null],[13,"Done","","Fold is complete and will return this value",5,null],[5,"cons_tuples","","Create an iterator that maps for example iterators of `((A, B), C)` to `(A, B, C)`.",null,{"inputs":[{"name":"i"}],"output":{"name":"constuples"}}],[5,"diff_with","","Compares every element yielded by both `i` and `j` with the given function in lock-step and returns a `Diff` which describes how `j` differs from `i`.",null,{"inputs":[{"name":"i"},{"name":"j"},{"name":"f"}],"output":{"generics":["diff"],"name":"option"}}],[5,"kmerge_by","","Create an iterator that merges elements of the contained iterators.",null,{"inputs":[{"name":"i"},{"name":"f"}],"output":{"name":"kmergeby"}}],[5,"repeat_n","","Create an iterator that produces `n` repetitions of `element`.",null,{"inputs":[{"name":"a"},{"name":"usize"}],"output":{"name":"repeatn"}}],[5,"repeat_call","","An iterator source that produces elements indefinitely by calling a given closure.",null,{"inputs":[{"name":"f"}],"output":{"name":"repeatcall"}}],[5,"unfold","","Creates a new unfold source with the specified closure as the \"iterator function\" and an initial state to eventually pass to the closure",null,{"inputs":[{"name":"st"},{"name":"f"}],"output":{"name":"unfold"}}],[5,"iterate","","Creates a new iterator that infinitely applies function to value and yields results.",null,{"inputs":[{"name":"st"},{"name":"f"}],"output":{"name":"iterate"}}],[5,"multizip","","An iterator that generalizes .zip() and allows running multiple iterators in lockstep.",null,{"inputs":[{"name":"u"}],"output":{"name":"zip"}}],[5,"interleave","","Create an iterator that interleaves elements in `i` and `j`.",null,{"inputs":[{"name":"i"},{"name":"j"}],"output":{"name":"interleave"}}],[5,"merge","","Create an iterator that merges elements in `i` and `j`.",null,{"inputs":[{"name":"i"},{"name":"j"}],"output":{"name":"merge"}}],[5,"put_back","","Create an iterator where you can put back a single item",null,{"inputs":[{"name":"i"}],"output":{"name":"putback"}}],[5,"put_back_n","","Create an iterator where you can put back multiple values to the front of the iteration.",null,{"inputs":[{"name":"i"}],"output":{"name":"putbackn"}}],[5,"multipeek","","An iterator adaptor that allows the user to peek at multiple `.next()` values without advancing the base iterator.",null,{"inputs":[{"name":"i"}],"output":{"name":"multipeek"}}],[5,"kmerge","","Create an iterator that merges elements of the contained iterators using the ordering function.",null,{"inputs":[{"name":"i"}],"output":{"name":"kmerge"}}],[5,"zip_eq","","Iterate `i` and `j` in lock step.",null,{"inputs":[{"name":"i"},{"name":"j"}],"output":{"name":"zipeq"}}],[5,"rciter","","Return an iterator inside a `Rc// Copyright 2016 lazy-static.rs Developers // @@ -129,7 +128,6 @@ unsafe impl<T: Sync> Sync for Lazy<T> {} #[macro_export] -#[doc(hidden)] macro_rules! __lazy_static_create { ($NAME:ident, $T:ty) => { static mut $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy(0 as *const $T, $crate::lazy::ONCE_INIT); diff --git a/master/src/lazy_static/lib.rs.html b/master/src/lazy_static/lib.rs.html index 83a2e4cf0..c32871df1 100644 --- a/master/src/lazy_static/lib.rs.html +++ b/master/src/lazy_static/lib.rs.html @@ -4,7 +4,7 @@ - +lib.rs.html -- source @@ -211,7 +211,69 @@ 155 156 157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212
+// Copyright 2016 lazy-static.rs Developers +// +// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or +// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or +// http://opensource.org/licenses/MIT>, at your option. This file may not be +// copied, modified, or distributed except according to those terms. + /*! A macro for declaring lazily evaluated statics. @@ -231,19 +293,34 @@ lazy_static! { } ``` -Metadata (such as doc comments) is allowed on each ref. +Attributes (including doc comments) are supported as well: -# Semantic +```rust +# #[macro_use] +# extern crate lazy_static; +# fn main() { +lazy_static! { + /// This is an example for using doc comment attributes + static ref EXAMPLE: u8 = 42; +} +# } +``` + +# Semantics For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that -implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up +implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Attributes end up attaching to this type.) On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs -can return a reference to the same object. +can return a reference to the same object. Note that this can lead to deadlocks +if you have multiple lazy statics that depend on each other in their initialization. -Like regular `static mut`s, this macro only works for types that fulfill the `Sync` -trait. +Apart from the lazy initialization, the resulting "static ref" variables +have generally the same properties as regular "static" variables: + +- Any type in them needs to fulfill the `Sync` trait. +- If the type has a destructor, then it will not run when the process exits. # Example @@ -282,93 +359,126 @@ The `Deref` implementation uses a hidden static variable that is guarded by a at */ -#![cfg_attr(feature="nightly", feature(const_fn, core_intrinsics))] -#![crate_type = "dylib"] +#![cfg_attr(feature="spin_no_std", feature(const_fn))] +#![cfg_attr(feature="nightly", feature(unreachable))] + +#![doc(html_root_url = "https://docs.rs/lazy_static/0.2.11")] +#![no_std] + +#[cfg(not(feature="nightly"))] +#[doc(hidden)] +pub mod lazy; + +#[cfg(all(feature="nightly", not(feature="spin_no_std")))] +#[path="nightly_lazy.rs"] +#[doc(hidden)] +pub mod lazy; + +#[cfg(all(feature="nightly", feature="spin_no_std"))] +#[path="core_lazy.rs"] +#[doc(hidden)] +pub mod lazy; + +#[doc(hidden)] +pub use core::ops::Deref as __Deref; + +#[macro_export] +#[doc(hidden)] +macro_rules! __lazy_static_internal { + // optional visibility restrictions are wrapped in `()` to allow for + // explicitly passing otherwise implicit information about private items + ($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { + __lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N); + __lazy_static_internal!(@TAIL, $N : $T = $e); + lazy_static!($($t)*); + }; + (@TAIL, $N:ident : $T:ty = $e:expr) => { + impl $crate::__Deref for $N { + type Target = $T; + #[allow(unsafe_code)] + fn deref(&self) -> &$T { + unsafe { + #[inline(always)] + fn __static_ref_initialize() -> $T { $e } + + #[inline(always)] + unsafe fn __stability() -> &'static $T { + __lazy_static_create!(LAZY, $T); + LAZY.get(__static_ref_initialize) + } + __stability() + } + } + } + impl $crate::LazyStatic for $N { + fn initialize(lazy: &Self) { + let _ = &**lazy; + } + } + }; + // `vis` is wrapped in `()` to prevent parsing ambiguity + (@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => { + #[allow(missing_copy_implementations)] + #[allow(non_camel_case_types)] + #[allow(dead_code)] + $(#[$attr])* + $($vis)* struct $N {__private_field: ()} + #[doc(hidden)] + $($vis)* static $N: $N = $N {__private_field: ()}; + }; + () => () +} #[macro_export] macro_rules! lazy_static { ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*); + // use `()` to explicitly forward the information about private items + __lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*); }; ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*); + __lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*); }; - ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { - lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N); - impl ::std::ops::Deref for $N { - type Target = $T; - fn deref<'a>(&'a self) -> &'a $T { - #[inline(always)] - fn __static_ref_initialize() -> $T { $e } - - unsafe { - use std::sync::{Once, ONCE_INIT}; - - #[inline(always)] - fn require_sync<T: Sync>(_: &T) { } - - #[inline(always)] - #[cfg(feature="nightly")] - unsafe fn __stability() -> &'static $T { - use std::cell::UnsafeCell; - - struct SyncCell(UnsafeCell<Option<$T>>); - unsafe impl Sync for SyncCell {} - - static DATA: SyncCell = SyncCell(UnsafeCell::new(None)); - static ONCE: Once = ONCE_INIT; - ONCE.call_once(|| { - *DATA.0.get() = Some(__static_ref_initialize()); - }); - match *DATA.0.get() { - Some(ref x) => x, - None => ::std::intrinsics::unreachable(), - } - } - - #[inline(always)] - #[cfg(not(feature="nightly"))] - unsafe fn __stability() -> &'static $T { - use std::mem::transmute; - use std::boxed::Box; - - static mut DATA: *const $T = 0 as *const $T; - static mut ONCE: Once = ONCE_INIT; - ONCE.call_once(|| { - DATA = transmute::<Box<$T>, *const $T>( - Box::new(__static_ref_initialize())); - }); - &*DATA - } - - let static_ref = __stability(); - require_sync(static_ref); - static_ref - } - } - } - lazy_static!($($t)*); - }; - (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => { - #[allow(missing_copy_implementations)] - #[allow(non_camel_case_types)] - #[allow(dead_code)] - $(#[$attr])* - pub struct $N {__private_field: ()} - #[doc(hidden)] - pub static $N: $N = $N {__private_field: ()}; - }; - (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => { - #[allow(missing_copy_implementations)] - #[allow(non_camel_case_types)] - #[allow(dead_code)] - $(#[$attr])* - struct $N {__private_field: ()} - #[doc(hidden)] - static $N: $N = $N {__private_field: ()}; + ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { + __lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*); }; () => () } + +/// Support trait for enabling a few common operation on lazy static values. +/// +/// This is implemented by each defined lazy static, and +/// used by the free functions in this crate. +pub trait LazyStatic { + #[doc(hidden)] + fn initialize(lazy: &Self); +} + +/// Takes a shared reference to a lazy static and initializes +/// it if it has not been already. +/// +/// This can be used to control the initialization point of a lazy static. +/// +/// Example: +/// +/// ```rust +/// #[macro_use] +/// extern crate lazy_static; +/// +/// lazy_static! { +/// static ref BUFFER: Vec<u8> = (0..65537).collect(); +/// } +/// +/// fn main() { +/// lazy_static::initialize(&BUFFER); +/// +/// // ... +/// work_with_initialized_data(&BUFFER); +/// } +/// # fn work_with_initialized_data(_: &[u8]) {} +/// ``` +pub fn initialize<T: LazyStatic>(lazy: &T) { + LazyStatic::initialize(lazy); +}