16
16
//!
17
17
//! [arc]: struct.Arc.html
18
18
19
- use boxed:: Box ;
20
-
21
19
use core:: sync:: atomic;
22
20
use core:: sync:: atomic:: Ordering :: { Acquire , Relaxed , Release , SeqCst } ;
23
21
use core:: borrow;
24
22
use core:: fmt;
25
23
use core:: cmp:: Ordering ;
26
24
use core:: intrinsics:: abort;
27
- use core:: mem;
28
- use core:: mem:: uninitialized;
25
+ use core:: mem:: { self , size_of_val, uninitialized} ;
29
26
use core:: ops:: Deref ;
30
27
use core:: ops:: CoerceUnsized ;
31
28
use core:: ptr:: { self , Shared } ;
@@ -34,7 +31,10 @@ use core::hash::{Hash, Hasher};
34
31
use core:: { isize, usize} ;
35
32
use core:: convert:: From ;
36
33
37
- use heap:: { Heap , Alloc , Layout } ;
34
+ use heap:: { Heap , Alloc , Layout , box_free} ;
35
+ use boxed:: Box ;
36
+ use string:: String ;
37
+ use vec:: Vec ;
38
38
39
39
/// A soft limit on the amount of references that may be made to an `Arc`.
40
40
///
@@ -532,6 +532,141 @@ impl<T: ?Sized> Arc<T> {
532
532
}
533
533
}
534
534
535
+ impl < T : ?Sized > Arc < T > {
536
+ // Allocates an `ArcInner<T>` with sufficient space for an unsized value
537
+ unsafe fn allocate_for_ptr ( ptr : * const T ) -> * mut ArcInner < T > {
538
+ // Create a fake ArcInner to find allocation size and alignment
539
+ let fake_ptr = ptr as * mut ArcInner < T > ;
540
+
541
+ let layout = Layout :: for_value ( & * fake_ptr) ;
542
+
543
+ let mem = Heap . alloc ( layout)
544
+ . unwrap_or_else ( |e| Heap . oom ( e) ) ;
545
+
546
+ // Initialize the real ArcInner
547
+ let inner = set_data_ptr ( ptr as * mut T , mem) as * mut ArcInner < T > ;
548
+
549
+ ptr:: write ( & mut ( * inner) . strong , atomic:: AtomicUsize :: new ( 1 ) ) ;
550
+ ptr:: write ( & mut ( * inner) . weak , atomic:: AtomicUsize :: new ( 1 ) ) ;
551
+
552
+ inner
553
+ }
554
+
555
+ fn from_box ( v : Box < T > ) -> Arc < T > {
556
+ unsafe {
557
+ let bptr = Box :: into_raw ( v) ;
558
+
559
+ let value_size = size_of_val ( & * bptr) ;
560
+ let ptr = Self :: allocate_for_ptr ( bptr) ;
561
+
562
+ // Copy value as bytes
563
+ ptr:: copy_nonoverlapping (
564
+ bptr as * const T as * const u8 ,
565
+ & mut ( * ptr) . data as * mut _ as * mut u8 ,
566
+ value_size) ;
567
+
568
+ // Free the allocation without dropping its contents
569
+ box_free ( bptr) ;
570
+
571
+ Arc { ptr : Shared :: new_unchecked ( ptr) }
572
+ }
573
+ }
574
+ }
575
+
576
+ // Sets the data pointer of a `?Sized` raw pointer.
577
+ //
578
+ // For a slice/trait object, this sets the `data` field and leaves the rest
579
+ // unchanged. For a sized raw pointer, this simply sets the pointer.
580
+ unsafe fn set_data_ptr < T : ?Sized , U > ( mut ptr : * mut T , data : * mut U ) -> * mut T {
581
+ ptr:: write ( & mut ptr as * mut _ as * mut * mut u8 , data as * mut u8 ) ;
582
+ ptr
583
+ }
584
+
585
+ impl < T > Arc < [ T ] > {
586
+ // Copy elements from slice into newly allocated Arc<[T]>
587
+ //
588
+ // Unsafe because the caller must either take ownership or bind `T: Copy`
589
+ unsafe fn copy_from_slice ( v : & [ T ] ) -> Arc < [ T ] > {
590
+ let v_ptr = v as * const [ T ] ;
591
+ let ptr = Self :: allocate_for_ptr ( v_ptr) ;
592
+
593
+ ptr:: copy_nonoverlapping (
594
+ v. as_ptr ( ) ,
595
+ & mut ( * ptr) . data as * mut [ T ] as * mut T ,
596
+ v. len ( ) ) ;
597
+
598
+ Arc { ptr : Shared :: new_unchecked ( ptr) }
599
+ }
600
+ }
601
+
602
+ // Specialization trait used for From<&[T]>
603
+ trait ArcFromSlice < T > {
604
+ fn from_slice ( slice : & [ T ] ) -> Self ;
605
+ }
606
+
607
+ impl < T : Clone > ArcFromSlice < T > for Arc < [ T ] > {
608
+ #[ inline]
609
+ default fn from_slice ( v : & [ T ] ) -> Self {
610
+ // Panic guard while cloning T elements.
611
+ // In the event of a panic, elements that have been written
612
+ // into the new ArcInner will be dropped, then the memory freed.
613
+ struct Guard < T > {
614
+ mem : * mut u8 ,
615
+ elems : * mut T ,
616
+ layout : Layout ,
617
+ n_elems : usize ,
618
+ }
619
+
620
+ impl < T > Drop for Guard < T > {
621
+ fn drop ( & mut self ) {
622
+ use core:: slice:: from_raw_parts_mut;
623
+
624
+ unsafe {
625
+ let slice = from_raw_parts_mut ( self . elems , self . n_elems ) ;
626
+ ptr:: drop_in_place ( slice) ;
627
+
628
+ Heap . dealloc ( self . mem , self . layout . clone ( ) ) ;
629
+ }
630
+ }
631
+ }
632
+
633
+ unsafe {
634
+ let v_ptr = v as * const [ T ] ;
635
+ let ptr = Self :: allocate_for_ptr ( v_ptr) ;
636
+
637
+ let mem = ptr as * mut _ as * mut u8 ;
638
+ let layout = Layout :: for_value ( & * ptr) ;
639
+
640
+ // Pointer to first element
641
+ let elems = & mut ( * ptr) . data as * mut [ T ] as * mut T ;
642
+
643
+ let mut guard = Guard {
644
+ mem : mem,
645
+ elems : elems,
646
+ layout : layout,
647
+ n_elems : 0 ,
648
+ } ;
649
+
650
+ for ( i, item) in v. iter ( ) . enumerate ( ) {
651
+ ptr:: write ( elems. offset ( i as isize ) , item. clone ( ) ) ;
652
+ guard. n_elems += 1 ;
653
+ }
654
+
655
+ // All clear. Forget the guard so it doesn't free the new ArcInner.
656
+ mem:: forget ( guard) ;
657
+
658
+ Arc { ptr : Shared :: new_unchecked ( ptr) }
659
+ }
660
+ }
661
+ }
662
+
663
+ impl < T : Copy > ArcFromSlice < T > for Arc < [ T ] > {
664
+ #[ inline]
665
+ fn from_slice ( v : & [ T ] ) -> Self {
666
+ unsafe { Arc :: copy_from_slice ( v) }
667
+ }
668
+ }
669
+
535
670
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
536
671
impl < T : ?Sized > Clone for Arc < T > {
537
672
/// Makes a clone of the `Arc` pointer.
@@ -1216,8 +1351,56 @@ impl<T> From<T> for Arc<T> {
1216
1351
}
1217
1352
}
1218
1353
1354
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1355
+ impl < ' a , T : Clone > From < & ' a [ T ] > for Arc < [ T ] > {
1356
+ #[ inline]
1357
+ fn from ( v : & [ T ] ) -> Arc < [ T ] > {
1358
+ <Self as ArcFromSlice < T > >:: from_slice ( v)
1359
+ }
1360
+ }
1361
+
1362
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1363
+ impl < ' a > From < & ' a str > for Arc < str > {
1364
+ #[ inline]
1365
+ fn from ( v : & str ) -> Arc < str > {
1366
+ unsafe { mem:: transmute ( <Arc < [ u8 ] > >:: from ( v. as_bytes ( ) ) ) }
1367
+ }
1368
+ }
1369
+
1370
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1371
+ impl From < String > for Arc < str > {
1372
+ #[ inline]
1373
+ fn from ( v : String ) -> Arc < str > {
1374
+ Arc :: from ( & v[ ..] )
1375
+ }
1376
+ }
1377
+
1378
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1379
+ impl < T : ?Sized > From < Box < T > > for Arc < T > {
1380
+ #[ inline]
1381
+ fn from ( v : Box < T > ) -> Arc < T > {
1382
+ Arc :: from_box ( v)
1383
+ }
1384
+ }
1385
+
1386
+ #[ stable( feature = "shared_from_slice" , since = "1.21.0" ) ]
1387
+ impl < T > From < Vec < T > > for Arc < [ T ] > {
1388
+ #[ inline]
1389
+ fn from ( mut v : Vec < T > ) -> Arc < [ T ] > {
1390
+ unsafe {
1391
+ let arc = Arc :: copy_from_slice ( & v) ;
1392
+
1393
+ // Allow the Vec to free its memory, but not destroy its contents
1394
+ v. set_len ( 0 ) ;
1395
+
1396
+ arc
1397
+ }
1398
+ }
1399
+ }
1400
+
1219
1401
#[ cfg( test) ]
1220
1402
mod tests {
1403
+ use std:: boxed:: Box ;
1221
1404
use std:: clone:: Clone ;
1222
1405
use std:: sync:: mpsc:: channel;
1223
1406
use std:: mem:: drop;
@@ -1520,6 +1703,113 @@ mod tests {
1520
1703
}
1521
1704
t. join ( ) . unwrap ( ) ;
1522
1705
}
1706
+
1707
+ #[ test]
1708
+ fn test_from_str ( ) {
1709
+ let r: Arc < str > = Arc :: from ( "foo" ) ;
1710
+
1711
+ assert_eq ! ( & r[ ..] , "foo" ) ;
1712
+ }
1713
+
1714
+ #[ test]
1715
+ fn test_copy_from_slice ( ) {
1716
+ let s: & [ u32 ] = & [ 1 , 2 , 3 ] ;
1717
+ let r: Arc < [ u32 ] > = Arc :: from ( s) ;
1718
+
1719
+ assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1720
+ }
1721
+
1722
+ #[ test]
1723
+ fn test_clone_from_slice ( ) {
1724
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
1725
+ struct X ( u32 ) ;
1726
+
1727
+ let s: & [ X ] = & [ X ( 1 ) , X ( 2 ) , X ( 3 ) ] ;
1728
+ let r: Arc < [ X ] > = Arc :: from ( s) ;
1729
+
1730
+ assert_eq ! ( & r[ ..] , s) ;
1731
+ }
1732
+
1733
+ #[ test]
1734
+ #[ should_panic]
1735
+ fn test_clone_from_slice_panic ( ) {
1736
+ use std:: string:: { String , ToString } ;
1737
+
1738
+ struct Fail ( u32 , String ) ;
1739
+
1740
+ impl Clone for Fail {
1741
+ fn clone ( & self ) -> Fail {
1742
+ if self . 0 == 2 {
1743
+ panic ! ( ) ;
1744
+ }
1745
+ Fail ( self . 0 , self . 1 . clone ( ) )
1746
+ }
1747
+ }
1748
+
1749
+ let s: & [ Fail ] = & [
1750
+ Fail ( 0 , "foo" . to_string ( ) ) ,
1751
+ Fail ( 1 , "bar" . to_string ( ) ) ,
1752
+ Fail ( 2 , "baz" . to_string ( ) ) ,
1753
+ ] ;
1754
+
1755
+ // Should panic, but not cause memory corruption
1756
+ let _r: Arc < [ Fail ] > = Arc :: from ( s) ;
1757
+ }
1758
+
1759
+ #[ test]
1760
+ fn test_from_box ( ) {
1761
+ let b: Box < u32 > = box 123 ;
1762
+ let r: Arc < u32 > = Arc :: from ( b) ;
1763
+
1764
+ assert_eq ! ( * r, 123 ) ;
1765
+ }
1766
+
1767
+ #[ test]
1768
+ fn test_from_box_str ( ) {
1769
+ use std:: string:: String ;
1770
+
1771
+ let s = String :: from ( "foo" ) . into_boxed_str ( ) ;
1772
+ let r: Arc < str > = Arc :: from ( s) ;
1773
+
1774
+ assert_eq ! ( & r[ ..] , "foo" ) ;
1775
+ }
1776
+
1777
+ #[ test]
1778
+ fn test_from_box_slice ( ) {
1779
+ let s = vec ! [ 1 , 2 , 3 ] . into_boxed_slice ( ) ;
1780
+ let r: Arc < [ u32 ] > = Arc :: from ( s) ;
1781
+
1782
+ assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1783
+ }
1784
+
1785
+ #[ test]
1786
+ fn test_from_box_trait ( ) {
1787
+ use std:: fmt:: Display ;
1788
+ use std:: string:: ToString ;
1789
+
1790
+ let b: Box < Display > = box 123 ;
1791
+ let r: Arc < Display > = Arc :: from ( b) ;
1792
+
1793
+ assert_eq ! ( r. to_string( ) , "123" ) ;
1794
+ }
1795
+
1796
+ #[ test]
1797
+ fn test_from_box_trait_zero_sized ( ) {
1798
+ use std:: fmt:: Debug ;
1799
+
1800
+ let b: Box < Debug > = box ( ) ;
1801
+ let r: Arc < Debug > = Arc :: from ( b) ;
1802
+
1803
+ assert_eq ! ( format!( "{:?}" , r) , "()" ) ;
1804
+ }
1805
+
1806
+ #[ test]
1807
+ fn test_from_vec ( ) {
1808
+ let v = vec ! [ 1 , 2 , 3 ] ;
1809
+ let r: Arc < [ u32 ] > = Arc :: from ( v) ;
1810
+
1811
+ assert_eq ! ( & r[ ..] , [ 1 , 2 , 3 ] ) ;
1812
+ }
1523
1813
}
1524
1814
1525
1815
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments