]> git.proxmox.com Git - rustc.git/blame - src/libstd/io/lazy.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / libstd / io / lazy.rs
CommitLineData
c34b1796
AL
1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
62682a34 11use cell::Cell;
e9174d1e 12use ptr;
a7813a04 13use sync::Arc;
e9174d1e 14use sys_common;
a7813a04 15use sys_common::mutex::Mutex;
c34b1796
AL
16
17pub struct Lazy<T> {
a7813a04 18 lock: Mutex,
62682a34
SL
19 ptr: Cell<*mut Arc<T>>,
20 init: fn() -> Arc<T>,
c34b1796
AL
21}
22
23unsafe impl<T> Sync for Lazy<T> {}
24
c34b1796 25impl<T: Send + Sync + 'static> Lazy<T> {
62682a34
SL
26 pub const fn new(init: fn() -> Arc<T>) -> Lazy<T> {
27 Lazy {
a7813a04 28 lock: Mutex::new(),
e9174d1e 29 ptr: Cell::new(ptr::null_mut()),
62682a34
SL
30 init: init
31 }
32 }
33
c34b1796 34 pub fn get(&'static self) -> Option<Arc<T>> {
c34b1796 35 unsafe {
a7813a04
XL
36 self.lock.lock();
37 let ptr = self.ptr.get();
38 let ret = if ptr.is_null() {
c34b1796
AL
39 Some(self.init())
40 } else if ptr as usize == 1 {
41 None
42 } else {
43 Some((*ptr).clone())
a7813a04
XL
44 };
45 self.lock.unlock();
46 return ret
c34b1796
AL
47 }
48 }
49
50 unsafe fn init(&'static self) -> Arc<T> {
51 // If we successfully register an at exit handler, then we cache the
52 // `Arc` allocation in our own internal box (it will get deallocated by
53 // the at exit handler). Otherwise we just return the freshly allocated
54 // `Arc`.
e9174d1e 55 let registered = sys_common::at_exit(move || {
a7813a04 56 self.lock.lock();
62682a34
SL
57 let ptr = self.ptr.get();
58 self.ptr.set(1 as *mut _);
a7813a04 59 self.lock.unlock();
c34b1796
AL
60 drop(Box::from_raw(ptr))
61 });
62 let ret = (self.init)();
63 if registered.is_ok() {
62682a34 64 self.ptr.set(Box::into_raw(Box::new(ret.clone())));
c34b1796 65 }
e9174d1e 66 ret
c34b1796
AL
67 }
68}