@@ -86,6 +86,31 @@ impl<T> Rc<T> {
86
86
}
87
87
}
88
88
89
+ impl < T : Clone > Rc < T > {
90
+ /// Acquires a mutable pointer to the inner contents by guaranteeing that
91
+ /// the reference count is one (no sharing is possible).
92
+ ///
93
+ /// This is also referred to as a copy-on-write operation because the inner
94
+ /// data is cloned if the reference count is greater than one.
95
+ #[ inline]
96
+ #[ experimental]
97
+ pub fn make_unique < ' a > ( & ' a mut self ) -> & ' a mut T {
98
+ // Note that we hold a strong reference, which also counts as
99
+ // a weak reference, so we only clone if there is an
100
+ // additional reference of either kind.
101
+ if self . strong ( ) != 1 || self . weak ( ) != 1 {
102
+ * self = Rc :: new ( self . deref ( ) . clone ( ) )
103
+ }
104
+ // This unsafety is ok because we're guaranteed that the pointer
105
+ // returned is the *only* pointer that will ever be returned to T. Our
106
+ // reference count is guaranteed to be 1 at this point, and we required
107
+ // the Rc itself to be `mut`, so we're returning the only possible
108
+ // reference to the inner data.
109
+ let inner = unsafe { & mut * self . _ptr } ;
110
+ & mut inner. value
111
+ }
112
+ }
113
+
89
114
impl < T > Deref < T > for Rc < T > {
90
115
/// Borrow the value contained in the reference-counted box
91
116
#[ inline( always) ]
@@ -234,6 +259,7 @@ impl<T> RcBoxPtr<T> for Weak<T> {
234
259
}
235
260
236
261
#[ cfg( test) ]
262
+ #[ allow( experimental) ]
237
263
mod tests {
238
264
use super :: { Rc , Weak } ;
239
265
use std:: cell:: RefCell ;
@@ -304,4 +330,66 @@ mod tests {
304
330
305
331
// hopefully we don't double-free (or leak)...
306
332
}
333
+
334
+ #[ test]
335
+ fn test_cowrc_clone_make_unique ( ) {
336
+ let mut cow0 = Rc :: new ( 75 u) ;
337
+ let mut cow1 = cow0. clone ( ) ;
338
+ let mut cow2 = cow1. clone ( ) ;
339
+
340
+ assert ! ( 75 == * cow0. make_unique( ) ) ;
341
+ assert ! ( 75 == * cow1. make_unique( ) ) ;
342
+ assert ! ( 75 == * cow2. make_unique( ) ) ;
343
+
344
+ * cow0. make_unique ( ) += 1 ;
345
+ * cow1. make_unique ( ) += 2 ;
346
+ * cow2. make_unique ( ) += 3 ;
347
+
348
+ assert ! ( 76 == * cow0) ;
349
+ assert ! ( 77 == * cow1) ;
350
+ assert ! ( 78 == * cow2) ;
351
+
352
+ // none should point to the same backing memory
353
+ assert ! ( * cow0 != * cow1) ;
354
+ assert ! ( * cow0 != * cow2) ;
355
+ assert ! ( * cow1 != * cow2) ;
356
+ }
357
+
358
+ #[ test]
359
+ fn test_cowrc_clone_unique2 ( ) {
360
+ let mut cow0 = Rc :: new ( 75 u) ;
361
+ let cow1 = cow0. clone ( ) ;
362
+ let cow2 = cow1. clone ( ) ;
363
+
364
+ assert ! ( 75 == * cow0) ;
365
+ assert ! ( 75 == * cow1) ;
366
+ assert ! ( 75 == * cow2) ;
367
+
368
+ * cow0. make_unique ( ) += 1 ;
369
+
370
+ assert ! ( 76 == * cow0) ;
371
+ assert ! ( 75 == * cow1) ;
372
+ assert ! ( 75 == * cow2) ;
373
+
374
+ // cow1 and cow2 should share the same contents
375
+ // cow0 should have a unique reference
376
+ assert ! ( * cow0 != * cow1) ;
377
+ assert ! ( * cow0 != * cow2) ;
378
+ assert ! ( * cow1 == * cow2) ;
379
+ }
380
+
381
+ #[ test]
382
+ fn test_cowrc_clone_weak ( ) {
383
+ let mut cow0 = Rc :: new ( 75 u) ;
384
+ let cow1_weak = cow0. downgrade ( ) ;
385
+
386
+ assert ! ( 75 == * cow0) ;
387
+ assert ! ( 75 == * cow1_weak. upgrade( ) . unwrap( ) ) ;
388
+
389
+ * cow0. make_unique ( ) += 1 ;
390
+
391
+ assert ! ( 76 == * cow0) ;
392
+ assert ! ( cow1_weak. upgrade( ) . is_none( ) ) ;
393
+ }
394
+
307
395
}
0 commit comments