1 // Copyright 2013 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.
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.
11 //! Implementation of running at_exit routines
13 //! Documentation can be found on the `rt::at_exit` function.
17 use alloc::boxed::Box;
18 use collections::vec::Vec;
22 use exclusive::Exclusive;
24 type Queue = Exclusive<Vec<proc():Send>>;
26 static mut QUEUE: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
27 static mut RUNNING: atomics::AtomicBool = atomics::INIT_ATOMIC_BOOL;
30 let state: Box<Queue> = box Exclusive::new(Vec::new());
32 rtassert!(!RUNNING.load(atomics::SeqCst));
33 rtassert!(QUEUE.swap(mem::transmute(state), atomics::SeqCst) == 0);
37 pub fn push(f: proc():Send) {
39 // Note that the check against 0 for the queue pointer is not atomic at
40 // all with respect to `run`, meaning that this could theoretically be a
41 // use-after-free. There's not much we can do to protect against that,
42 // however. Let's just assume a well-behaved runtime and go from there!
43 rtassert!(!RUNNING.load(atomics::SeqCst));
44 let queue = QUEUE.load(atomics::SeqCst);
45 rtassert!(queue != 0);
46 (*(queue as *const Queue)).lock().push(f);
52 rtassert!(!RUNNING.load(atomics::SeqCst));
53 let queue = QUEUE.swap(0, atomics::SeqCst);
54 rtassert!(queue != 0);
56 let queue: Box<Queue> = mem::transmute(queue);
57 let v = mem::replace(&mut *queue.lock(), Vec::new());
61 for to_run in cur.move_iter() {