diff options
author | Simon Sapin <simon.sapin@exyr.org> | 2015-08-14 14:34:13 +0200 |
---|---|---|
committer | Simon Sapin <simon.sapin@exyr.org> | 2015-08-20 16:49:48 +0200 |
commit | 649250130b221685dfa8e570ae07d0d2f634bd40 (patch) | |
tree | 13d4a188e49d12874824f1c7ce98725846baf126 /components/layout/flow_ref.rs | |
parent | 2d22aa8e7e99ef52198e0f5918a2a16483aaba0e (diff) | |
download | servo-649250130b221685dfa8e570ae07d0d2f634bd40.tar.gz servo-649250130b221685dfa8e570ae07d0d2f634bd40.zip |
Replace FlowRef with Arc<Flow>, now that Arc supports DST.
… and WeakFlowRef with Weak<Flow>.
Diffstat (limited to 'components/layout/flow_ref.rs')
-rw-r--r-- | components/layout/flow_ref.rs | 189 |
1 files changed, 7 insertions, 182 deletions
diff --git a/components/layout/flow_ref.rs b/components/layout/flow_ref.rs index b7d143734fb..7408a2ac2fb 100644 --- a/components/layout/flow_ref.rs +++ b/components/layout/flow_ref.rs @@ -10,190 +10,15 @@ #![allow(unsafe_code)] -use flow; -use flow::{Flow, BaseFlow}; +use flow::Flow; +use std::sync::{Arc, Weak}; -use std::mem; -use std::ops::Deref; -use std::ptr; -use std::raw; -use std::rt::heap; -use std::sync::atomic::{self, Ordering}; - -#[unsafe_no_drop_flag] -pub struct FlowRef { - object: raw::TraitObject, -} - -unsafe impl Send for FlowRef {} -unsafe impl Sync for FlowRef {} - -#[unsafe_no_drop_flag] -pub struct WeakFlowRef { - object: raw::TraitObject, -} - -unsafe impl Send for WeakFlowRef {} -unsafe impl Sync for WeakFlowRef {} - -impl FlowRef { - pub fn new(mut flow: Box<Flow>) -> FlowRef { - unsafe { - let result = { - let flow_ref: &mut Flow = &mut *flow; - let object = mem::transmute::<&mut Flow, raw::TraitObject>(flow_ref); - FlowRef { object: object } - }; - mem::forget(flow); - result - } - } - - /// Downgrades the FlowRef to a WeakFlowRef. - pub fn downgrade(&self) -> WeakFlowRef { - unsafe { - flow::base(&**self).weak_ref_count().fetch_add(1, Ordering::Relaxed); - } - WeakFlowRef { object: self.object } - } -} - -impl<'a> Deref for FlowRef { - type Target = Flow + 'a; - fn deref(&self) -> &(Flow + 'a) { - unsafe { - mem::transmute_copy::<raw::TraitObject, &(Flow + 'a)>(&self.object) - } - } -} +pub type FlowRef = Arc<Flow>; +pub type WeakFlowRef = Weak<Flow>; // FIXME(https://github.com/servo/servo/issues/6503) This introduces unsound mutable aliasing. // Try to replace it with Arc::get_mut (which checks that the reference count is 1). -pub unsafe fn deref_mut<'a>(flow_ref: &mut FlowRef) -> &mut (Flow + 'a) { - mem::transmute_copy::<raw::TraitObject, &mut (Flow + 'a)>(&flow_ref.object) -} - -impl Drop for FlowRef { - fn drop(&mut self) { - unsafe { - if self.object.vtable.is_null() || - self.object.vtable as usize == mem::POST_DROP_USIZE { - return - } - if flow::base(&**self).strong_ref_count().fetch_sub(1, Ordering::Release) != 1 { - return - } - atomic::fence(Ordering::Acquire); - - // Normally we'd call the underlying Drop logic but not free the - // allocation, but this is almost impossible without DST in - // Rust. Instead we make a fake trait object to run the drop logic - // on. - let flow_ref: FlowRef = mem::replace(self, FlowRef { - object: raw::TraitObject { - vtable: ptr::null_mut(), - data: ptr::null_mut(), - } - }); - - let vtable: &[usize; 3] = mem::transmute::<*mut (), &[usize; 3]>(flow_ref.object.vtable); - let object_size = vtable[1]; - let object_align = vtable[2]; - - let fake_data = heap::allocate(object_size, object_align); - ptr::copy(flow_ref.object.data as *const u8, fake_data, object_size); - - let fake_box = raw::TraitObject { vtable: flow_ref.object.vtable, data: fake_data as *mut () }; - let fake_flow = mem::transmute::<raw::TraitObject, Box<Flow>>(fake_box); - drop(fake_flow); - - if flow::base(&*flow_ref).weak_ref_count().fetch_sub(1, Ordering::Release) == 1 { - atomic::fence(Ordering::Acquire); - heap::deallocate(flow_ref.object.data as *mut u8, object_size, object_align); - } - - mem::forget(flow_ref); - } - } -} - -impl Clone for FlowRef { - fn clone(&self) -> FlowRef { - unsafe { - let _ = flow::base(&**self).strong_ref_count().fetch_add(1, Ordering::Relaxed); - FlowRef { - object: raw::TraitObject { - vtable: self.object.vtable, - data: self.object.data, - } - } - } - } -} - -fn base<'a>(r: &WeakFlowRef) -> &'a BaseFlow { - let data = r.object.data; - debug_assert!(!data.is_null()); - unsafe { - mem::transmute::<*mut (), &'a BaseFlow>(data) - } -} - -impl WeakFlowRef { - /// Upgrades a WeakFlowRef to a FlowRef. - pub fn upgrade(&self) -> Option<FlowRef> { - unsafe { - let object = base(self); - // We use a CAS loop to increment the strong count instead of a - // fetch_add because once the count hits 0 is must never be above - // 0. - loop { - let n = object.strong_ref_count().load(Ordering::SeqCst); - if n == 0 { return None } - let old = object.strong_ref_count().compare_and_swap(n, n + 1, Ordering::SeqCst); - if old == n { - return Some(FlowRef { object: self.object }) - } - } - } - } -} - -impl Clone for WeakFlowRef { - fn clone(&self) -> WeakFlowRef { - unsafe { - base(self).weak_ref_count().fetch_add(1, Ordering::Relaxed); - } - WeakFlowRef { object: self. object } - } -} - -impl Drop for WeakFlowRef { - fn drop(&mut self) { - unsafe { - if self.object.vtable.is_null() || - self.object.vtable as usize == mem::POST_DROP_USIZE { - return - } - - if base(self).weak_ref_count().fetch_sub(1, Ordering::Release) == 1 { - atomic::fence(Ordering::Acquire); - - // This dance deallocates the Box<Flow> without running its - // drop glue. The drop glue is run when the last strong - // reference is released. - let weak_ref: WeakFlowRef = mem::replace(self, WeakFlowRef { - object: raw::TraitObject { - vtable: ptr::null_mut(), - data: ptr::null_mut(), - } - }); - let vtable: &[usize; 3] = mem::transmute::<*mut (), &[usize; 3]>(weak_ref.object.vtable); - let object_size = vtable[1]; - let object_align = vtable[2]; - heap::deallocate(weak_ref.object.data as *mut u8, object_size, object_align); - mem::forget(weak_ref); - } - } - } +pub unsafe fn deref_mut<'a>(r: &'a mut FlowRef) -> &'a mut Flow { + let ptr: *const Flow = &**r; + &mut *(ptr as *mut Flow) } |