1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// Reference-counted pointers to flows.
///
/// Eventually, with dynamically sized types in Rust, much of this code will be superfluous.
use flow::Flow;
use flow;
use std::mem;
use std::ptr;
use std::raw;
use std::sync::atomics::SeqCst;
#[unsafe_no_drop_flag]
pub struct FlowRef {
object: raw::TraitObject,
}
impl FlowRef {
pub fn new(mut flow: Box<Flow>) -> FlowRef {
unsafe {
let result = {
let flow_ref: &mut Flow = flow;
let object = mem::transmute::<&mut Flow, raw::TraitObject>(flow_ref);
FlowRef { object: object }
};
mem::forget(flow);
result
}
}
pub fn get<'a>(&'a self) -> &'a Flow {
unsafe {
mem::transmute_copy::<raw::TraitObject, &'a Flow>(&self.object)
}
}
pub fn get_mut<'a>(&'a mut self) -> &'a mut Flow {
unsafe {
mem::transmute_copy::<raw::TraitObject, &'a mut Flow>(&self.object)
}
}
}
impl Drop for FlowRef {
fn drop(&mut self) {
unsafe {
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 {
object: raw::TraitObject {
vtable: ptr::mut_null(),
data: ptr::mut_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();
}
}
}
impl Clone for FlowRef {
fn clone(&self) -> FlowRef {
unsafe {
drop(flow::base(self.get()).ref_count().fetch_add(1, SeqCst));
FlowRef {
object: raw::TraitObject {
vtable: self.object.vtable,
data: self.object.data,
}
}
}
}
}
|