aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/flow_ref.rs
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2015-08-14 14:34:13 +0200
committerSimon Sapin <simon.sapin@exyr.org>2015-08-20 16:49:48 +0200
commit649250130b221685dfa8e570ae07d0d2f634bd40 (patch)
tree13d4a188e49d12874824f1c7ce98725846baf126 /components/layout/flow_ref.rs
parent2d22aa8e7e99ef52198e0f5918a2a16483aaba0e (diff)
downloadservo-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.rs189
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)
}