(index<- ) ./libstd/rt/rc.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! An owned, task-local, reference counted type
12 //!
13 //! # Safety note
14 //!
15 //! XXX There is currently no type-system mechanism for enforcing that
16 //! reference counted types are both allocated on the exchange heap
17 //! and also non-sendable
18 //!
19 //! This doesn't prevent borrowing multiple aliasable mutable pointers
20
21 use ops::Drop;
22 use clone::Clone;
23 use libc::c_void;
24 use cast;
25
26 pub struct RC<T> {
27 p: *c_void // ~(uint, T)
28 }
29
30 impl<T> RC<T> {
31 pub fn new(val: T) -> RC<T> {
32 unsafe {
33 let v = ~(1, val);
34 let p: *c_void = cast::transmute(v);
35 RC { p: p }
36 }
37 }
38
39 fn get_mut_state(&mut self) -> *mut (uint, T) {
40 unsafe {
41 let p: &mut ~(uint, T) = cast::transmute(&mut self.p);
42 let p: *mut (uint, T) = &mut **p;
43 return p;
44 }
45 }
46
47 fn get_state(&self) -> *(uint, T) {
48 unsafe {
49 let p: &~(uint, T) = cast::transmute(&self.p);
50 let p: *(uint, T) = &**p;
51 return p;
52 }
53 }
54
55 pub fn unsafe_borrow_mut(&mut self) -> *mut T {
56 unsafe {
57 match *self.get_mut_state() {
58 (_, ref mut p) => {
59 let p: *mut T = p;
60 return p;
61 }
62 }
63 }
64 }
65
66 pub fn refcount(&self) -> uint {
67 unsafe {
68 match *self.get_state() {
69 (count, _) => count
70 }
71 }
72 }
73 }
74
75 #[unsafe_destructor]
76 impl<T> Drop for RC<T> {
77 fn drop(&mut self) {
78 assert!(self.refcount() > 0);
79
80 unsafe {
81 match *self.get_mut_state() {
82 (ref mut count, _) => {
83 *count = *count - 1
84 }
85 }
86
87 if self.refcount() == 0 {
88 let _: ~(uint, T) = cast::transmute(self.p);
89 }
90 }
91 }
92 }
93
94 impl<T> Clone for RC<T> {
95 fn clone(&self) -> RC<T> {
96 unsafe {
97 // XXX: Mutable clone
98 let this: &mut RC<T> = cast::transmute_mut(self);
99
100 match *this.get_mut_state() {
101 (ref mut count, _) => {
102 *count = *count + 1;
103 }
104 }
105 }
106
107 RC { p: self.p }
108 }
109 }
110
111 #[cfg(test)]
112 mod test {
113 use super::RC;
114
115 #[test]
116 fn smoke_test() {
117 unsafe {
118 let mut v1 = RC::new(100);
119 assert!(*v1.unsafe_borrow_mut() == 100);
120 assert!(v1.refcount() == 1);
121
122 let mut v2 = v1.clone();
123 assert!(*v2.unsafe_borrow_mut() == 100);
124 assert!(v2.refcount() == 2);
125
126 *v2.unsafe_borrow_mut() = 200;
127 assert!(*v2.unsafe_borrow_mut() == 200);
128 assert!(*v1.unsafe_borrow_mut() == 200);
129
130 let v3 = v2.clone();
131 assert!(v3.refcount() == 3);
132 {
133 let _v1 = v1;
134 let _v2 = v2;
135 }
136 assert!(v3.refcount() == 1);
137 }
138 }
139 }