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::MutableSeq;
19 use collections::vec::Vec;
23 use exclusive::Exclusive;
25 type Queue = Exclusive<Vec<proc():Send>>;
27 static mut QUEUE: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
28 static mut RUNNING: atomic::AtomicBool = atomic::INIT_ATOMIC_BOOL;
31 let state: Box<Queue> = box Exclusive::new(Vec::new());
33 rtassert!(!RUNNING.load(atomic::SeqCst));
34 assert!(QUEUE.swap(mem::transmute(state), atomic::SeqCst) == 0);
38 pub fn push(f: proc():Send) {
40 // Note that the check against 0 for the queue pointer is not atomic at
41 // all with respect to `run`, meaning that this could theoretically be a
42 // use-after-free. There's not much we can do to protect against that,
43 // however. Let's just assume a well-behaved runtime and go from there!
44 rtassert!(!RUNNING.load(atomic::SeqCst));
45 let queue = QUEUE.load(atomic::SeqCst);
46 rtassert!(queue != 0);
47 (*(queue as *const Queue)).lock().push(f);
53 rtassert!(!RUNNING.load(atomic::SeqCst));
54 let queue = QUEUE.swap(0, atomic::SeqCst);
55 rtassert!(queue != 0);
57 let queue: Box<Queue> = mem::transmute(queue);
58 let v = mem::replace(&mut *queue.lock(), Vec::new());
62 for to_run in cur.move_iter() {