Skip to content

Commit c1d6f5e

Browse files
committed
libextra: De-@mut the arena
1 parent c38456a commit c1d6f5e

File tree

1 file changed

+34
-27
lines changed

1 file changed

+34
-27
lines changed

src/libextra/arena.rs

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@
3535
#[allow(missing_doc)];
3636

3737

38-
use list::{MutList, MutCons, MutNil};
38+
use list::{List, Cons, Nil};
39+
use list;
3940

4041
use std::at_vec;
4142
use std::cast::{transmute, transmute_mut, transmute_mut_region};
4243
use std::cast;
44+
use std::cell::{Cell, RefCell};
4345
use std::num;
4446
use std::ptr;
4547
use std::mem;
@@ -50,10 +52,11 @@ use std::unstable::intrinsics::{TyDesc, get_tydesc};
5052
// The way arena uses arrays is really deeply awful. The arrays are
5153
// allocated, and have capacities reserved, but the fill for the array
5254
// will always stay at 0.
55+
#[deriving(Clone)]
5356
struct Chunk {
54-
data: @[u8],
55-
fill: uint,
56-
is_pod: bool,
57+
data: RefCell<@[u8]>,
58+
fill: Cell<uint>,
59+
is_pod: Cell<bool>,
5760
}
5861

5962
#[no_freeze]
@@ -63,7 +66,7 @@ pub struct Arena {
6366
// access the head.
6467
priv head: Chunk,
6568
priv pod_head: Chunk,
66-
priv chunks: @mut MutList<Chunk>,
69+
priv chunks: RefCell<@List<Chunk>>,
6770
}
6871

6972
impl Arena {
@@ -75,7 +78,7 @@ impl Arena {
7578
Arena {
7679
head: chunk(initial_size, false),
7780
pod_head: chunk(initial_size, true),
78-
chunks: @mut MutNil,
81+
chunks: RefCell::new(@Nil),
7982
}
8083
}
8184
}
@@ -84,9 +87,9 @@ fn chunk(size: uint, is_pod: bool) -> Chunk {
8487
let mut v: @[u8] = @[];
8588
unsafe { at_vec::raw::reserve(&mut v, size); }
8689
Chunk {
87-
data: unsafe { cast::transmute(v) },
88-
fill: 0u,
89-
is_pod: is_pod,
90+
data: RefCell::new(unsafe { cast::transmute(v) }),
91+
fill: Cell::new(0u),
92+
is_pod: Cell::new(is_pod),
9093
}
9194
}
9295

@@ -95,8 +98,9 @@ impl Drop for Arena {
9598
fn drop(&mut self) {
9699
unsafe {
97100
destroy_chunk(&self.head);
98-
self.chunks.each(|chunk| {
99-
if !chunk.is_pod {
101+
102+
list::each(self.chunks.get(), |chunk| {
103+
if !chunk.is_pod.get() {
100104
destroy_chunk(chunk);
101105
}
102106
true
@@ -114,8 +118,11 @@ fn round_up_to(base: uint, align: uint) -> uint {
114118
// in it.
115119
unsafe fn destroy_chunk(chunk: &Chunk) {
116120
let mut idx = 0;
117-
let buf = chunk.data.as_ptr();
118-
let fill = chunk.fill;
121+
let buf = {
122+
let data = chunk.data.borrow();
123+
data.get().as_ptr()
124+
};
125+
let fill = chunk.fill.get();
119126

120127
while idx < fill {
121128
let tydesc_data: *uint = transmute(ptr::offset(buf, idx as int));
@@ -155,9 +162,9 @@ impl Arena {
155162
// Functions for the POD part of the arena
156163
fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 {
157164
// Allocate a new chunk.
158-
let chunk_size = at_vec::capacity(self.pod_head.data);
165+
let chunk_size = at_vec::capacity(self.pod_head.data.get());
159166
let new_min_chunk_size = num::max(n_bytes, chunk_size);
160-
self.chunks = @mut MutCons(self.pod_head, self.chunks);
167+
self.chunks.set(@Cons(self.pod_head.clone(), self.chunks.get()));
161168
self.pod_head =
162169
chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true);
163170

@@ -168,17 +175,17 @@ impl Arena {
168175
fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 {
169176
unsafe {
170177
let this = transmute_mut_region(self);
171-
let start = round_up_to(this.pod_head.fill, align);
178+
let start = round_up_to(this.pod_head.fill.get(), align);
172179
let end = start + n_bytes;
173-
if end > at_vec::capacity(this.pod_head.data) {
180+
if end > at_vec::capacity(this.pod_head.data.get()) {
174181
return this.alloc_pod_grow(n_bytes, align);
175182
}
176-
this.pod_head.fill = end;
183+
this.pod_head.fill.set(end);
177184

178185
//debug!("idx = {}, size = {}, align = {}, fill = {}",
179-
// start, n_bytes, align, head.fill);
186+
// start, n_bytes, align, head.fill.get());
180187

181-
ptr::offset(this.pod_head.data.as_ptr(), start as int)
188+
ptr::offset(this.pod_head.data.get().as_ptr(), start as int)
182189
}
183190
}
184191

@@ -197,9 +204,9 @@ impl Arena {
197204
fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint)
198205
-> (*u8, *u8) {
199206
// Allocate a new chunk.
200-
let chunk_size = at_vec::capacity(self.head.data);
207+
let chunk_size = at_vec::capacity(self.head.data.get());
201208
let new_min_chunk_size = num::max(n_bytes, chunk_size);
202-
self.chunks = @mut MutCons(self.head, self.chunks);
209+
self.chunks.set(@Cons(self.head.clone(), self.chunks.get()));
203210
self.head =
204211
chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false);
205212

@@ -218,23 +225,23 @@ impl Arena {
218225
{
219226
let head = transmute_mut_region(&mut self.head);
220227

221-
tydesc_start = head.fill;
222-
after_tydesc = head.fill + mem::size_of::<*TyDesc>();
228+
tydesc_start = head.fill.get();
229+
after_tydesc = head.fill.get() + mem::size_of::<*TyDesc>();
223230
start = round_up_to(after_tydesc, align);
224231
end = start + n_bytes;
225232
}
226233

227-
if end > at_vec::capacity(self.head.data) {
234+
if end > at_vec::capacity(self.head.data.get()) {
228235
return self.alloc_nonpod_grow(n_bytes, align);
229236
}
230237

231238
let head = transmute_mut_region(&mut self.head);
232-
head.fill = round_up_to(end, mem::pref_align_of::<*TyDesc>());
239+
head.fill.set(round_up_to(end, mem::pref_align_of::<*TyDesc>()));
233240

234241
//debug!("idx = {}, size = {}, align = {}, fill = {}",
235242
// start, n_bytes, align, head.fill);
236243

237-
let buf = self.head.data.as_ptr();
244+
let buf = self.head.data.get().as_ptr();
238245
return (ptr::offset(buf, tydesc_start as int), ptr::offset(buf, start as int));
239246
}
240247
}

0 commit comments

Comments
 (0)