auto merge of #18127 : alexcrichton/rust/deriving-arc, r=aturon

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!
This commit is contained in:
bors 2014-10-28 08:01:52 +00:00
commit faed6489da
2 changed files with 54 additions and 20 deletions

View File

@ -16,13 +16,15 @@
use core::atomic; use core::atomic;
use core::clone::Clone; use core::clone::Clone;
use core::fmt::{mod, Show}; use core::fmt::{mod, Show};
use core::cmp::{Eq, Ord, PartialEq, PartialOrd, Ordering};
use core::default::Default;
use core::kinds::{Sync, Send}; use core::kinds::{Sync, Send};
use core::mem::{min_align_of, size_of, drop}; use core::mem::{min_align_of, size_of, drop};
use core::mem; use core::mem;
use core::ops::{Drop, Deref}; use core::ops::{Drop, Deref};
use core::option::{Some, None, Option}; use core::option::{Some, None, Option};
use core::ptr;
use core::ptr::RawPtr; use core::ptr::RawPtr;
use core::ptr;
use heap::deallocate; use heap::deallocate;
/// An atomically reference counted wrapper for shared state. /// An atomically reference counted wrapper for shared state.
@ -92,16 +94,6 @@ impl<T: Sync + Send> Arc<T> {
Arc { _ptr: unsafe { mem::transmute(x) } } 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. /// Downgrades a strong pointer to a weak pointer.
/// ///
/// Weak pointers will not keep the data alive. Once all strong references /// Weak pointers will not keep the data alive. Once all strong references
@ -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"] #[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. /// Duplicate an atomically reference counted wrapper.
/// ///
/// The resulting two `Arc` objects will point to the same underlying data /// The resulting two `Arc` objects will point to the same underlying data
@ -141,19 +145,13 @@ impl<T: Sync + Send> Clone for Arc<T> {
} }
#[experimental = "Deref is experimental."] #[experimental = "Deref is experimental."]
impl<T: Send + Sync> Deref<T> for Arc<T> { impl<T> Deref<T> for Arc<T> {
#[inline] #[inline]
fn deref(&self) -> &T { fn deref(&self) -> &T {
&self.inner().data &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> { impl<T: Send + Sync + Clone> Arc<T> {
/// Acquires a mutable pointer to the inner contents by guaranteeing that /// Acquires a mutable pointer to the inner contents by guaranteeing that
/// the reference count is one (no sharing is possible). /// the reference count is one (no sharing is possible).
@ -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)] #[cfg(test)]
#[allow(experimental)] #[allow(experimental)]
mod tests { mod tests {
@ -440,4 +470,8 @@ mod tests {
let a = Arc::new(5u32); let a = Arc::new(5u32);
assert!(format!("{}", a).as_slice() == "5") 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> }
} }

View File

@ -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> { fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s) (**self).encode(s)
} }