(index<- )        ./libstd/rt/at_exit_imp.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
  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.
  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  
 11  //! Implementation of running at_exit routines
 12  //!
 13  //! Documentation can be found on the `rt::at_exit` function.
 14  
 15  use cast;
 16  use iter::Iterator;
 17  use kinds::Send;
 18  use mem;
 19  use option::{Some, None};
 20  use owned::Box;
 21  use ptr::RawPtr;
 22  use unstable::sync::Exclusive;
 23  use slice::OwnedVector;
 24  use vec::Vec;
 25  
 26  type Queue = Exclusive<Vec<proc():Send>>;
 27  
 28  // You'll note that these variables are *not* atomic, and this is done on
 29  // purpose. This module is designed to have init() called *once* in a
 30  // single-task context, and then run() is called only once in another
 31  // single-task context. As a result of this, only the `push` function is
 32  // thread-safe, and it assumes that the `init` function has run previously.
 33  static mut QUEUE: *mut Queue = 0 as *mut Queue;
 34  static mut RUNNING: bool = false;
 35  
 36  pub fn init() {
 37      unsafe {
 38          rtassert!(!RUNNING);
 39          rtassert!(QUEUE.is_null());
 40          let stateBox<Queue> = box Exclusive::new(vec!());
 41          QUEUE = cast::transmute(state);
 42      }
 43  }
 44  
 45  pub fn push(f: proc():Send) {
 46      unsafe {
 47          rtassert!(!RUNNING);
 48          rtassert!(!QUEUE.is_null());
 49          let state&mut Queue = cast::transmute(QUEUE);
 50          let mut f = Some(f);
 51          state.with(|arr|  {
 52              arr.push(f.take_unwrap());
 53          });
 54      }
 55  }
 56  
 57  pub fn run() {
 58      let vec = unsafe {
 59          rtassert!(!RUNNING);
 60          rtassert!(!QUEUE.is_null());
 61          RUNNING = true;
 62          let stateBox<Queue> = cast::transmute(QUEUE);
 63          QUEUE = 0 as *mut Queue;
 64          let mut vec = None;
 65          state.with(|arr| {
 66              vec = Some(mem::replace(arr, vec!()));
 67          });
 68          vec.take_unwrap()
 69      };
 70  
 71  
 72      for f in vec.move_iter() {
 73          f();
 74      }
 75  }