Skip to content

Commit

Permalink
alloc: Make deriving more friendly with Arc
Browse files Browse the repository at this point in the history
This adds impls of Eq/Ord/PartialEq/PartialOrd/Show/Default to Arc<T>, and it
also removes the `Send + Sync` bound on the `Clone` impl of Arc to make it more
deriving-friendly. The `Send + Sync` requirement is still enforce on
construction, of course!
  • Loading branch information
alexcrichton committed Oct 28, 2014
1 parent 823f805 commit 35ad00d
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 20 deletions.
72 changes: 53 additions & 19 deletions src/liballoc/arc.rs
Expand Up @@ -16,13 +16,15 @@
use core::atomic;
use core::clone::Clone;
use core::fmt::{mod, Show};
use core::cmp::{Eq, Ord, PartialEq, PartialOrd, Ordering};
use core::default::Default;
use core::kinds::{Sync, Send};
use core::mem::{min_align_of, size_of, drop};
use core::mem;
use core::ops::{Drop, Deref};
use core::option::{Some, None, Option};
use core::ptr;
use core::ptr::RawPtr;
use core::ptr;
use heap::deallocate;

/// An atomically reference counted wrapper for shared state.
Expand Down Expand Up @@ -92,16 +94,6 @@ impl<T: Sync + Send> Arc<T> {
Arc { _ptr: unsafe { mem::transmute(x) } }
}

#[inline]
fn inner(&self) -> &ArcInner<T> {
// This unsafety is ok because while this arc is alive we're guaranteed
// that the inner pointer is valid. Furthermore, we know that the
// `ArcInner` structure itself is `Sync` because the inner data is
// `Sync` as well, so we're ok loaning out an immutable pointer to
// these contents.
unsafe { &*self._ptr }
}

/// Downgrades a strong pointer to a weak pointer.
///
/// Weak pointers will not keep the data alive. Once all strong references
Expand All @@ -115,8 +107,20 @@ impl<T: Sync + Send> Arc<T> {
}
}

impl<T> Arc<T> {
#[inline]
fn inner(&self) -> &ArcInner<T> {
// This unsafety is ok because while this arc is alive we're guaranteed
// that the inner pointer is valid. Furthermore, we know that the
// `ArcInner` structure itself is `Sync` because the inner data is
// `Sync` as well, so we're ok loaning out an immutable pointer to
// these contents.
unsafe { &*self._ptr }
}
}

#[unstable = "waiting on stability of Clone"]
impl<T: Sync + Send> Clone for Arc<T> {
impl<T> Clone for Arc<T> {
/// Duplicate an atomically reference counted wrapper.
///
/// The resulting two `Arc` objects will point to the same underlying data
Expand All @@ -141,19 +145,13 @@ impl<T: Sync + Send> Clone for Arc<T> {
}

#[experimental = "Deref is experimental."]
impl<T: Send + Sync> Deref<T> for Arc<T> {
impl<T> Deref<T> for Arc<T> {
#[inline]
fn deref(&self) -> &T {
&self.inner().data
}
}

impl<T: Send + Sync + Show> Show for Arc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}

impl<T: Send + Sync + Clone> Arc<T> {
/// Acquires a mutable pointer to the inner contents by guaranteeing that
/// the reference count is one (no sharing is possible).
Expand Down Expand Up @@ -279,6 +277,38 @@ impl<T: Sync + Send> Drop for Weak<T> {
}
}

#[unstable = "waiting on PartialEq"]
impl<T: PartialEq> PartialEq for Arc<T> {
fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
}
#[unstable = "waiting on PartialOrd"]
impl<T: PartialOrd> PartialOrd for Arc<T> {
fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
}
#[unstable = "waiting on Ord"]
impl<T: Ord> Ord for Arc<T> {
fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
}
#[unstable = "waiting on Eq"]
impl<T: Eq> Eq for Arc<T> {}

impl<T: fmt::Show> fmt::Show for Arc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}

impl<T: Default + Sync + Send> Default for Arc<T> {
fn default() -> Arc<T> { Arc::new(Default::default()) }
}

#[cfg(test)]
#[allow(experimental)]
mod tests {
Expand Down Expand Up @@ -440,4 +470,8 @@ mod tests {
let a = Arc::new(5u32);
assert!(format!("{}", a).as_slice() == "5")
}

// Make sure deriving works with Arc<T>
#[deriving(Eq, Ord, PartialEq, PartialOrd, Clone, Show, Default)]
struct Foo { inner: Arc<int> }
}
2 changes: 1 addition & 1 deletion src/libserialize/serialize.rs
Expand Up @@ -557,7 +557,7 @@ impl<E, D: Decoder<E>, T: Decodable<D, E>> Decodable<D, E> for RefCell<T> {
}
}

impl<E, S:Encoder<E>, T:Encodable<S, E>+Send+Sync> Encodable<S, E> for Arc<T> {
impl<E, S:Encoder<E>, T:Encodable<S, E>> Encodable<S, E> for Arc<T> {
fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
Expand Down

5 comments on commit 35ad00d

@bors
Copy link
Contributor

@bors bors commented on 35ad00d Oct 28, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from aturon
at alexcrichton@35ad00d

@bors
Copy link
Contributor

@bors bors commented on 35ad00d Oct 28, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging alexcrichton/rust/deriving-arc = 35ad00d into auto

@bors
Copy link
Contributor

@bors bors commented on 35ad00d Oct 28, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alexcrichton/rust/deriving-arc = 35ad00d merged ok, testing candidate = faed648

@bors
Copy link
Contributor

@bors bors commented on 35ad00d Oct 28, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 35ad00d Oct 28, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = faed648

Please sign in to comment.