@@ -19,98 +19,103 @@ use ops::Drop;
19
19
use clone:: Clone ;
20
20
use kinds:: Owned ;
21
21
22
- /****************************************************************************
23
- * Shared state & exclusive ARC
24
- ****************************************************************************/
25
-
26
- struct ArcData < T > {
27
- count : libc:: intptr_t ,
28
- // FIXME(#3224) should be able to make this non-option to save memory
29
- data : Option < T > ,
22
+ /// An atomically reference counted pointer.
23
+ ///
24
+ /// Enforces no shared-memory safety.
25
+ pub struct UnsafeAtomicRcBox < T > {
26
+ data : * mut libc:: c_void ,
30
27
}
31
28
32
- struct ArcDestruct < T > {
33
- data : * libc:: c_void ,
29
+ struct AtomicRcBoxData < T > {
30
+ count : int ,
31
+ data : Option < T > ,
34
32
}
35
33
36
- #[ unsafe_destructor]
37
- impl < T > Drop for ArcDestruct < T > {
38
- fn finalize ( & self ) {
34
+ impl < T : Owned > UnsafeAtomicRcBox < T > {
35
+ pub fn new ( data : T ) -> UnsafeAtomicRcBox < T > {
39
36
unsafe {
40
- do task:: unkillable {
41
- let mut data : ~ArcData <T > = cast:: transmute ( self . data ) ;
42
- let new_count =
43
- intrinsics:: atomic_xsub ( & mut data. count , 1 ) - 1 ;
44
- assert ! ( new_count >= 0 ) ;
45
- if new_count == 0 {
46
- // drop glue takes over.
47
- } else {
48
- cast:: forget ( data) ;
49
- }
50
- }
37
+ let data = ~AtomicRcBoxData { count : 1 , data : Some ( data) } ;
38
+ let ptr = cast:: transmute ( data) ;
39
+ return UnsafeAtomicRcBox { data : ptr } ;
51
40
}
52
41
}
53
- }
54
42
55
- fn ArcDestruct < T > ( data : * libc:: c_void ) -> ArcDestruct < T > {
56
- ArcDestruct {
57
- data : data
43
+ #[ inline( always) ]
44
+ #[ cfg( stage0) ]
45
+ pub unsafe fn get ( & self ) -> * mut T
46
+ {
47
+ let mut data: ~AtomicRcBoxData < T > = cast:: transmute ( self . data ) ;
48
+ assert ! ( data. count > 0 ) ;
49
+ let r: * mut T = cast:: transmute ( data. data . get_mut_ref ( ) ) ;
50
+ cast:: forget ( data) ;
51
+ return r;
58
52
}
59
- }
60
53
61
- /**
62
- * COMPLETELY UNSAFE. Used as a primitive for the safe versions in std::arc.
63
- *
64
- * Data races between tasks can result in crashes and, with sufficient
65
- * cleverness, arbitrary type coercion.
66
- */
67
- pub type SharedMutableState < T > = ArcDestruct < T > ;
54
+ #[ inline( always) ]
55
+ #[ cfg( not( stage0) ) ]
56
+ pub unsafe fn get ( & self ) -> * mut T
57
+ {
58
+ let mut data: ~AtomicRcBoxData < T > = cast:: transmute ( self . data ) ;
59
+ assert ! ( data. count > 0 ) ;
60
+ let r: * mut T = data. data . get_mut_ref ( ) ;
61
+ cast:: forget ( data) ;
62
+ return r;
63
+ }
68
64
69
- pub unsafe fn shared_mutable_state < T : Owned > ( data : T ) ->
70
- SharedMutableState < T > {
71
- let data = ~ArcData { count : 1 , data : Some ( data) } ;
72
- let ptr = cast:: transmute ( data) ;
73
- ArcDestruct ( ptr)
74
- }
65
+ #[ inline( always) ]
66
+ #[ cfg( stage0) ]
67
+ pub unsafe fn get_immut ( & self ) -> * T
68
+ {
69
+ let mut data: ~AtomicRcBoxData < T > = cast:: transmute ( self . data ) ;
70
+ assert ! ( data. count > 0 ) ;
71
+ let r: * T = cast:: transmute ( data. data . get_mut_ref ( ) ) ;
72
+ cast:: forget ( data) ;
73
+ return r;
74
+ }
75
75
76
- #[ inline( always) ]
77
- pub unsafe fn get_shared_mutable_state < T : Owned > (
78
- rc : * SharedMutableState < T > ) -> * mut T
79
- {
80
- let ptr: ~ArcData < T > = cast:: transmute ( ( * rc) . data ) ;
81
- assert ! ( ptr. count > 0 ) ;
82
- let r = cast:: transmute ( ptr. data . get_ref ( ) ) ;
83
- cast:: forget ( ptr) ;
84
- return r;
85
- }
86
- #[ inline( always) ]
87
- pub unsafe fn get_shared_immutable_state < ' a , T : Owned > (
88
- rc : & ' a SharedMutableState < T > ) -> & ' a T {
89
- let ptr: ~ArcData < T > = cast:: transmute ( ( * rc) . data ) ;
90
- assert ! ( ptr. count > 0 ) ;
91
- // Cast us back into the correct region
92
- let r = cast:: transmute_region ( ptr. data . get_ref ( ) ) ;
93
- cast:: forget ( ptr) ;
94
- return r;
76
+ #[ inline( always) ]
77
+ #[ cfg( not( stage0) ) ]
78
+ pub unsafe fn get_immut ( & self ) -> * T
79
+ {
80
+ let mut data: ~AtomicRcBoxData < T > = cast:: transmute ( self . data ) ;
81
+ assert ! ( data. count > 0 ) ;
82
+ let r: * T = cast:: transmute_immut ( data. data . get_mut_ref ( ) ) ;
83
+ cast:: forget ( data) ;
84
+ return r;
85
+ }
95
86
}
96
87
97
- pub unsafe fn clone_shared_mutable_state < T : Owned > ( rc : & SharedMutableState < T > )
98
- -> SharedMutableState < T > {
99
- let mut ptr: ~ArcData < T > = cast:: transmute ( ( * rc) . data ) ;
100
- let new_count = intrinsics:: atomic_xadd ( & mut ptr. count , 1 ) + 1 ;
101
- assert ! ( new_count >= 2 ) ;
102
- cast:: forget ( ptr) ;
103
- ArcDestruct ( ( * rc) . data )
88
+ impl < T : Owned > Clone for UnsafeAtomicRcBox < T > {
89
+ fn clone ( & self ) -> UnsafeAtomicRcBox < T > {
90
+ unsafe {
91
+ let mut data: ~AtomicRcBoxData < T > = cast:: transmute ( self . data ) ;
92
+ let new_count = intrinsics:: atomic_xadd ( & mut data. count , 1 ) + 1 ;
93
+ assert ! ( new_count >= 2 ) ;
94
+ cast:: forget ( data) ;
95
+ return UnsafeAtomicRcBox { data : self . data } ;
96
+ }
97
+ }
104
98
}
105
99
106
- impl < T : Owned > Clone for SharedMutableState < T > {
107
- fn clone ( & self ) -> SharedMutableState < T > {
100
+ #[ unsafe_destructor]
101
+ impl < T > Drop for UnsafeAtomicRcBox < T > {
102
+ fn finalize ( & self ) {
108
103
unsafe {
109
- clone_shared_mutable_state ( self )
104
+ do task:: unkillable {
105
+ let mut data : ~AtomicRcBoxData <T > = cast:: transmute ( self . data ) ;
106
+ let new_count = intrinsics:: atomic_xsub ( & mut data. count , 1 ) - 1 ;
107
+ assert ! ( new_count >= 0 ) ;
108
+ if new_count == 0 {
109
+ // drop glue takes over.
110
+ } else {
111
+ cast:: forget ( data) ;
112
+ }
113
+ }
110
114
}
111
115
}
112
116
}
113
117
118
+
114
119
/****************************************************************************/
115
120
116
121
#[ allow( non_camel_case_types) ] // runtime type
@@ -160,7 +165,7 @@ struct ExData<T> {
160
165
* An arc over mutable data that is protected by a lock. For library use only.
161
166
*/
162
167
pub struct Exclusive < T > {
163
- x : SharedMutableState < ExData < T > >
168
+ x : UnsafeAtomicRcBox < ExData < T > >
164
169
}
165
170
166
171
pub fn exclusive < T : Owned > ( user_data : T ) -> Exclusive < T > {
@@ -170,16 +175,14 @@ pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
170
175
data : user_data
171
176
} ;
172
177
Exclusive {
173
- x : unsafe {
174
- shared_mutable_state ( data)
175
- }
178
+ x : UnsafeAtomicRcBox :: new ( data)
176
179
}
177
180
}
178
181
179
182
impl < T : Owned > Clone for Exclusive < T > {
180
183
// Duplicate an exclusive ARC, as std::arc::clone.
181
184
fn clone ( & self ) -> Exclusive < T > {
182
- Exclusive { x : unsafe { clone_shared_mutable_state ( & self . x ) } }
185
+ Exclusive { x : self . x . clone ( ) }
183
186
}
184
187
}
185
188
@@ -192,7 +195,7 @@ pub impl<T:Owned> Exclusive<T> {
192
195
// the exclusive. Supporting that is a work in progress.
193
196
#[ inline( always) ]
194
197
unsafe fn with < U > ( & self , f : & fn ( x : & mut T ) -> U ) -> U {
195
- let rec = get_shared_mutable_state ( & self . x ) ;
198
+ let rec = self . x . get ( ) ;
196
199
do ( * rec) . lock . lock {
197
200
if ( * rec) . failed {
198
201
fail ! (
0 commit comments