From 19d44f2d2491cc2c5f603da79737dacac84715ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 3 Dec 2017 13:49:46 +0100 Subject: [PATCH] Make arenas thread safe --- src/Cargo.lock | 3 ++ src/libarena/Cargo.toml | 3 ++ src/libarena/lib.rs | 71 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/src/Cargo.lock b/src/Cargo.lock index daa8d0dc84ce..e03d9454d062 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -66,6 +66,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "arena" version = "0.0.0" +dependencies = [ + "rustc_data_structures 0.0.0", +] [[package]] name = "arrayvec" diff --git a/src/libarena/Cargo.toml b/src/libarena/Cargo.toml index b53c0a2f48bf..e2af67dd9286 100644 --- a/src/libarena/Cargo.toml +++ b/src/libarena/Cargo.toml @@ -7,3 +7,6 @@ version = "0.0.0" name = "arena" path = "lib.rs" crate-type = ["dylib"] + +[dependencies] +rustc_data_structures = { path = "../librustc_data_structures" } \ No newline at end of file diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b319f333342c..c79e0e14e3d8 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -32,6 +32,9 @@ #![allow(deprecated)] extern crate alloc; +extern crate rustc_data_structures; + +use rustc_data_structures::sync::MTLock; use std::cell::{Cell, RefCell}; use std::cmp; @@ -290,6 +293,8 @@ pub struct DroplessArena { chunks: RefCell>>, } +unsafe impl Send for DroplessArena {} + impl DroplessArena { pub fn new() -> DroplessArena { DroplessArena { @@ -410,6 +415,72 @@ impl DroplessArena { } } +pub struct SyncTypedArena { + lock: MTLock>, +} + +impl SyncTypedArena { + #[inline(always)] + pub fn new() -> SyncTypedArena { + SyncTypedArena { + lock: MTLock::new(TypedArena::new()) + } + } + + #[inline(always)] + pub fn alloc(&self, object: T) -> &mut T { + // Extend the lifetime of the result since it's limited to the lock guard + unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) } + } + + #[inline(always)] + pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] + where + T: Copy, + { + // Extend the lifetime of the result since it's limited to the lock guard + unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) } + } + + #[inline(always)] + pub fn clear(&mut self) { + self.lock.get_mut().clear(); + } +} + +pub struct SyncDroplessArena { + lock: MTLock, +} + +impl SyncDroplessArena { + #[inline(always)] + pub fn new() -> SyncDroplessArena { + SyncDroplessArena { + lock: MTLock::new(DroplessArena::new()) + } + } + + #[inline(always)] + pub fn in_arena(&self, ptr: *const T) -> bool { + self.lock.lock().in_arena(ptr) + } + + #[inline(always)] + pub fn alloc(&self, object: T) -> &mut T { + // Extend the lifetime of the result since it's limited to the lock guard + unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) } + } + + #[inline(always)] + pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] + where + T: Copy, + { + // Extend the lifetime of the result since it's limited to the lock guard + unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) } + } +} + #[cfg(test)] mod tests { extern crate test;