]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/local_heap.rs
8715e768e32767a72e960c7e08826a1cb6256716
[rust.git] / src / libstd / rt / local_heap.rs
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 //! The local, garbage collected heap
12
13 use libc;
14 use libc::{c_void, uintptr_t, size_t};
15 use ops::Drop;
16 use option::{Some, None};
17 use rt::local::Local;
18 use rt::task::Task;
19 use unstable::raw;
20
21 type MemoryRegion = c_void;
22
23 struct Env { priv opaque: () }
24
25 struct BoxedRegion {
26     env: *Env,
27     backing_region: *MemoryRegion,
28     live_allocs: *raw::Box<()>,
29 }
30
31 pub type OpaqueBox = c_void;
32 pub type TypeDesc = c_void;
33
34 pub struct LocalHeap {
35     memory_region: *MemoryRegion,
36     boxed_region: *BoxedRegion
37 }
38
39 impl LocalHeap {
40     pub fn new() -> LocalHeap {
41         unsafe {
42             // Don't need synchronization for the single-threaded local heap
43             let synchronized = false as uintptr_t;
44             // XXX: These usually come from the environment
45             let detailed_leaks = false as uintptr_t;
46             let poison_on_free = false as uintptr_t;
47             let region = rust_new_memory_region(synchronized, detailed_leaks, poison_on_free);
48             assert!(region.is_not_null());
49             let boxed = rust_new_boxed_region(region, poison_on_free);
50             assert!(boxed.is_not_null());
51             LocalHeap {
52                 memory_region: region,
53                 boxed_region: boxed
54             }
55         }
56     }
57
58     pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox {
59         unsafe {
60             return rust_boxed_region_malloc(self.boxed_region, td, size as size_t);
61         }
62     }
63
64     pub fn realloc(&mut self, ptr: *OpaqueBox, size: uint) -> *OpaqueBox {
65         unsafe {
66             return rust_boxed_region_realloc(self.boxed_region, ptr, size as size_t);
67         }
68     }
69
70     pub fn free(&mut self, box: *OpaqueBox) {
71         unsafe {
72             return rust_boxed_region_free(self.boxed_region, box);
73         }
74     }
75 }
76
77 impl Drop for LocalHeap {
78     fn drop(&self) {
79         unsafe {
80             rust_delete_boxed_region(self.boxed_region);
81             rust_delete_memory_region(self.memory_region);
82         }
83     }
84 }
85
86 // A little compatibility function
87 pub unsafe fn local_free(ptr: *libc::c_char) {
88     // XXX: Unsafe borrow for speed. Lame.
89     match Local::try_unsafe_borrow::<Task>() {
90         Some(task) => {
91             (*task).heap.free(ptr as *libc::c_void);
92         }
93         None => rtabort!("local free outside of task")
94     }
95 }
96
97 pub fn live_allocs() -> *raw::Box<()> {
98     let region = do Local::borrow::<Task, *BoxedRegion> |task| {
99         task.heap.boxed_region
100     };
101
102     return unsafe { (*region).live_allocs };
103 }
104
105 extern {
106     #[fast_ffi]
107     fn rust_new_memory_region(synchronized: uintptr_t,
108                                detailed_leaks: uintptr_t,
109                                poison_on_free: uintptr_t) -> *MemoryRegion;
110     #[fast_ffi]
111     fn rust_delete_memory_region(region: *MemoryRegion);
112     #[fast_ffi]
113     fn rust_new_boxed_region(region: *MemoryRegion,
114                              poison_on_free: uintptr_t) -> *BoxedRegion;
115     #[fast_ffi]
116     fn rust_delete_boxed_region(region: *BoxedRegion);
117     #[fast_ffi]
118     fn rust_boxed_region_malloc(region: *BoxedRegion,
119                                 td: *TypeDesc,
120                                 size: size_t) -> *OpaqueBox;
121     #[fast_ffi]
122     fn rust_boxed_region_realloc(region: *BoxedRegion,
123                                  ptr: *OpaqueBox,
124                                  size: size_t) -> *OpaqueBox;
125     #[fast_ffi]
126     fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
127 }
128
129 #[cfg(test)]
130 mod bench {
131     use extra::test::BenchHarness;
132
133     #[bench]
134     fn alloc_managed_small(bh: &mut BenchHarness) {
135         do bh.iter {
136             @10;
137         }
138     }
139
140     #[bench]
141     fn alloc_managed_big(bh: &mut BenchHarness) {
142         do bh.iter {
143             @[10, ..1000];
144         }
145     }
146 }