]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/rc.rs
Change finalize -> drop.
[rust.git] / src / 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(&self) {
78         assert!(self.refcount() > 0);
79
80         unsafe {
81             // FIXME(#4330) Need self by value to get mutability.
82             let this: &mut RC<T> = cast::transmute_mut(self);
83
84             match *this.get_mut_state() {
85                 (ref mut count, _) => {
86                     *count = *count - 1
87                 }
88             }
89
90             if this.refcount() == 0 {
91                 let _: ~(uint, T) = cast::transmute(this.p);
92             }
93         }
94     }
95 }
96
97 impl<T> Clone for RC<T> {
98     fn clone(&self) -> RC<T> {
99         unsafe {
100             // XXX: Mutable clone
101             let this: &mut RC<T> = cast::transmute_mut(self);
102
103             match *this.get_mut_state() {
104                 (ref mut count, _) => {
105                     *count = *count + 1;
106                 }
107             }
108         }
109
110         RC { p: self.p }
111     }
112 }
113
114 #[cfg(test)]
115 mod test {
116     use super::RC;
117
118     #[test]
119     fn smoke_test() {
120         unsafe {
121             let mut v1 = RC::new(100);
122             assert!(*v1.unsafe_borrow_mut() == 100);
123             assert!(v1.refcount() == 1);
124
125             let mut v2 = v1.clone();
126             assert!(*v2.unsafe_borrow_mut() == 100);
127             assert!(v2.refcount() == 2);
128
129             *v2.unsafe_borrow_mut() = 200;
130             assert!(*v2.unsafe_borrow_mut() == 200);
131             assert!(*v1.unsafe_borrow_mut() == 200);
132
133             let v3 = v2.clone();
134             assert!(v3.refcount() == 3);
135             {
136                 let _v1 = v1;
137                 let _v2 = v2;
138             }
139             assert!(v3.refcount() == 1);
140         }
141     }
142 }