(index<- )        ./libstd/cleanup.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Wed Apr  9 17:27:02 2014
   1  // Copyright 2012 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  #![doc(hidden)]
  12  
  13  use ptr;
  14  use raw;
  15  
  16  static RC_IMMORTAL : uint = 0x77777777;
  17  
  18  /*
  19   * Box annihilation
  20   *
  21   * This runs at task death to free all boxes.
  22   */
  23  
  24  unsafe fn each_live_alloc(read_next_before: bool,
  25                            f: |alloc: *mut raw::Box<()>-> bool)
  26                            -> bool {
  27      //! Walks the internal list of allocations
  28  
  29      use rt::local_heap;
  30  
  31      let mut alloc = local_heap::live_allocs();
  32      while alloc != ptr::mut_null() {
  33          let next_before = (*alloc).next;
  34  
  35          if !f(alloc) {
  36              return false;
  37          }
  38  
  39          if read_next_before {
  40              alloc = next_before;
  41          } else {
  42              alloc = (*alloc).next;
  43          }
  44      }
  45      return true;
  46  }
  47  
  48  #[cfg(unix)]
  49  fn debug_mem() -> bool {
  50      // FIXME: Need to port the environment struct to newsched
  51      false
  52  }
  53  
  54  #[cfg(windows)]
  55  fn debug_mem() -> bool {
  56      false
  57  }
  58  
  59  /// Destroys all managed memory (i.e. @ boxes) held by the current task.
  60  pub unsafe fn annihilate() {
  61      use rt::local_heap::local_free;
  62  
  63      let mut n_total_boxes = 0u;
  64  
  65      // Pass 1: Make all boxes immortal.
  66      //
  67      // In this pass, nothing gets freed, so it does not matter whether
  68      // we read the next field before or after the callback.
  69      each_live_alloc(true, |alloc| {
  70          n_total_boxes += 1;
  71          (*alloc).ref_count = RC_IMMORTAL;
  72          true
  73      });
  74  
  75      // Pass 2: Drop all boxes.
  76      //
  77      // In this pass, unique-managed boxes may get freed, but not
  78      // managed boxes, so we must read the `next` field *after* the
  79      // callback, as the original value may have been freed.
  80      each_live_alloc(false, |alloc| {
  81          let drop_glue = (*alloc).drop_glue;
  82          let data = &mut (*alloc).data as *mut ();
  83          drop_glue(data as *mut u8);
  84          true
  85      });
  86  
  87      // Pass 3: Free all boxes.
  88      //
  89      // In this pass, managed boxes may get freed (but not
  90      // unique-managed boxes, though I think that none of those are
  91      // left), so we must read the `next` field before, since it will
  92      // not be valid after.
  93      each_live_alloc(true, |alloc| {
  94          local_free(alloc as *u8);
  95          true
  96      });
  97  
  98      if debug_mem() {
  99          // We do logging here w/o allocation.
 100          println!("total boxes annihilated: {}", n_total_boxes);
 101      }
 102  }