Merge pull request #3170 from SimonSapin/trait-object-transmute

Transmute std::raw::TraitObject rather than (some) custom tuples/structs
This commit is contained in:
Simon Sapin 2014-08-29 00:35:55 +01:00
commit aea6f849a0
3 changed files with 38 additions and 28 deletions

View file

@ -57,6 +57,7 @@ use std::mem;
use std::num::Zero;
use std::fmt;
use std::iter::Zip;
use std::raw;
use std::sync::atomics::{AtomicUint, Relaxed, SeqCst};
use std::slice::MutItems;
use style::computed_values::{clear, position, text_align};
@ -274,8 +275,8 @@ pub trait Flow: fmt::Show + ToString + Share {
#[inline(always)]
pub fn base<'a>(this: &'a Flow) -> &'a BaseFlow {
unsafe {
let (_, ptr): (uint, &BaseFlow) = mem::transmute(this);
ptr
let obj = mem::transmute::<&'a Flow, raw::TraitObject>(this);
mem::transmute::<*mut (), &'a BaseFlow>(obj.data)
}
}
@ -287,8 +288,8 @@ pub fn imm_child_iter<'a>(flow: &'a Flow) -> FlowListIterator<'a> {
#[inline(always)]
pub fn mut_base<'a>(this: &'a mut Flow) -> &'a mut BaseFlow {
unsafe {
let (_, ptr): (uint, &mut BaseFlow) = mem::transmute(this);
ptr
let obj = mem::transmute::<&'a mut Flow, raw::TraitObject>(this);
mem::transmute::<*mut (), &'a mut BaseFlow>(obj.data)
}
}

View file

@ -11,16 +11,14 @@ use flow_ref::FlowRef;
use std::kinds::marker::ContravariantLifetime;
use std::mem;
use std::ptr;
use std::raw;
pub type Link = Option<FlowRef>;
// FIXME: use TraitObject instead of duplicating the type
#[allow(raw_pointer_deriving)]
#[deriving(Clone)]
pub struct Rawlink<'a> {
vtable: *mut (),
obj: *mut (),
object: raw::TraitObject,
marker: ContravariantLifetime<'a>,
}
@ -50,23 +48,29 @@ impl<'a> Rawlink<'a> {
/// Like Option::None for Rawlink
pub fn none() -> Rawlink<'static> {
Rawlink {
vtable: ptr::mut_null(),
obj: ptr::mut_null(),
object: raw::TraitObject {
vtable: ptr::mut_null(),
data: ptr::mut_null(),
},
marker: ContravariantLifetime,
}
}
/// Like Option::Some for Rawlink
pub fn some(n: &Flow) -> Rawlink {
unsafe { mem::transmute(n) }
unsafe {
Rawlink {
object: mem::transmute::<&Flow, raw::TraitObject>(n),
marker: ContravariantLifetime,
}
}
}
pub unsafe fn resolve_mut(&self) -> Option<&'a mut Flow> {
if self.obj.is_null() {
if self.object.data.is_null() {
None
} else {
let me: &mut Flow = mem::transmute_copy(self);
Some(me)
Some(mem::transmute_copy::<raw::TraitObject, &mut Flow>(&self.object))
}
}
}

View file

@ -11,13 +11,12 @@ use flow;
use std::mem;
use std::ptr;
use std::raw;
use std::sync::atomics::SeqCst;
// FIXME: This should probably be a wrapper on TraitObject.
#[unsafe_no_drop_flag]
pub struct FlowRef {
vtable: *const u8,
ptr: *const u8,
object: raw::TraitObject,
}
impl FlowRef {
@ -25,7 +24,8 @@ impl FlowRef {
unsafe {
let result = {
let flow_ref: &mut Flow = flow;
mem::transmute(flow_ref)
let object = mem::transmute::<&mut Flow, raw::TraitObject>(flow_ref);
FlowRef { object: object }
};
mem::forget(flow);
result
@ -34,13 +34,13 @@ impl FlowRef {
pub fn get<'a>(&'a self) -> &'a Flow {
unsafe {
mem::transmute_copy(self)
mem::transmute_copy::<raw::TraitObject, &'a Flow>(&self.object)
}
}
pub fn get_mut<'a>(&'a mut self) -> &'a mut Flow {
unsafe {
mem::transmute_copy(self)
mem::transmute_copy::<raw::TraitObject, &'a mut Flow>(&self.object)
}
}
}
@ -48,19 +48,22 @@ impl FlowRef {
impl Drop for FlowRef {
fn drop(&mut self) {
unsafe {
if self.vtable == ptr::null() {
if self.object.vtable.is_null() {
return
}
if flow::base(self.get()).ref_count().fetch_sub(1, SeqCst) > 1 {
return
}
let flow_ref: FlowRef = mem::replace(self, FlowRef {
vtable: ptr::null(),
ptr: ptr::null(),
object: raw::TraitObject {
vtable: ptr::mut_null(),
data: ptr::mut_null(),
}
});
drop(mem::transmute::<FlowRef,Box<Flow>>(flow_ref));
self.vtable = ptr::null();
self.ptr = ptr::null();
drop(mem::transmute::<raw::TraitObject, Box<Flow>>(flow_ref.object));
mem::forget(flow_ref);
self.object.vtable = ptr::mut_null();
self.object.data = ptr::mut_null();
}
}
}
@ -70,8 +73,10 @@ impl Clone for FlowRef {
unsafe {
drop(flow::base(self.get()).ref_count().fetch_add(1, SeqCst));
FlowRef {
vtable: self.vtable,
ptr: self.ptr,
object: raw::TraitObject {
vtable: self.object.vtable,
data: self.object.data,
}
}
}
}