Implement From<&[T]> and others for Arc/Rc · rust-lang/rust@8e0d01b (original) (raw)

`@@ -16,16 +16,13 @@

`

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 {

`

532

532

`}

`

533

533

`}

`

534

534

``

``

535

`+

impl<T: ?Sized> Arc {

`

``

536

`` +

// Allocates an ArcInner<T> with sufficient space for an unsized value

``

``

537

`+

unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner {

`

``

538

`+

// Create a fake ArcInner to find allocation size and alignment

`

``

539

`+

let fake_ptr = ptr as *mut ArcInner;

`

``

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;

`

``

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) -> Arc {

`

``

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 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 {

`

``

604

`+

fn from_slice(slice: &[T]) -> Self;

`

``

605

`+

}

`

``

606

+

``

607

`+

impl<T: Clone> ArcFromSlice 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 {

`

``

614

`+

mem: *mut u8,

`

``

615

`+

elems: *mut T,

`

``

616

`+

layout: Layout,

`

``

617

`+

n_elems: usize,

`

``

618

`+

}

`

``

619

+

``

620

`+

impl Drop for Guard {

`

``

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 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 {

`

537

672

`` /// Makes a clone of the Arc pointer.

``

`@@ -1216,8 +1351,56 @@ impl From for Arc {

`

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>::from_slice(v)

`

``

1359

`+

}

`

``

1360

`+

}

`

``

1361

+

``

1362

`+

#[stable(feature = "shared_from_slice", since = "1.21.0")]

`

``

1363

`+

impl<'a> From<&'a str> for Arc {

`

``

1364

`+

#[inline]

`

``

1365

`+

fn from(v: &str) -> Arc {

`

``

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 for Arc {

`

``

1372

`+

#[inline]

`

``

1373

`+

fn from(v: String) -> Arc {

`

``

1374

`+

Arc::from(&v[..])

`

``

1375

`+

}

`

``

1376

`+

}

`

``

1377

+

``

1378

`+

#[stable(feature = "shared_from_slice", since = "1.21.0")]

`

``

1379

`+

impl<T: ?Sized> From<Box> for Arc {

`

``

1380

`+

#[inline]

`

``

1381

`+

fn from(v: Box) -> Arc {

`

``

1382

`+

Arc::from_box(v)

`

``

1383

`+

}

`

``

1384

`+

}

`

``

1385

+

``

1386

`+

#[stable(feature = "shared_from_slice", since = "1.21.0")]

`

``

1387

`+

impl From<Vec> for Arc<[T]> {

`

``

1388

`+

#[inline]

`

``

1389

`+

fn from(mut v: Vec) -> 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 = 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, 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 = box 123;

`

``

1762

`+

let r: Arc = Arc::from(b);

`

``

1763

+

``

1764

`+

assert_eq!(*r, 123);

`

``

1765

`+

}

`

``

1766

+

``

1767

`+

#[test]

`

``

1768

`+

fn test_from_box_str() {

`

``

1769

`+

use std:🧵:String;

`

``

1770

+

``

1771

`+

let s = String::from("foo").into_boxed_str();

`

``

1772

`+

let r: Arc = 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:🧵:ToString;

`

``

1789

+

``

1790

`+

let b: Box = box 123;

`

``

1791

`+

let r: Arc = 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 = box ();

`

``

1801

`+

let r: Arc = 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")]

`