From: Chris Morgan Date: Sat, 18 Apr 2015 06:13:58 +0000 (+1000) Subject: Implement stuff for concurrency. X-Git-Tag: 0.11.0~4 X-Git-Url: https://git.chrismorgan.info/anymap/commitdiff_plain/fdba2f45b9b9d6fa05be6a4d0849add42d94516e Implement stuff for concurrency. This took some refactoring too for best effect. --- diff --git a/.travis.yml b/.travis.yml index 2248e9b..64c99e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,13 @@ env: global: - secure: nR+DJRUQ9v03nNZMpMu1tGKLKBAqdQsTIAr8ffdl+DUEh3b2jvQ+vLLNFLPjsloqhoOXo7cWO7qVpiE4ZOq2lNDURQjdiZGFjh/Y5+xKy2BqFdV7qQ1JoBzsMyx28tQTYz0mtBsACiCYKKb+ddNX5hpwrsjp8cS7htZktA5kbiU= script: - - [[ "$(rustc --version)" =~ -dev ]] && cargo test --features nightly || ! cargo test --features nightly - - [[ "$(rustc --version)" =~ -dev ]] && cargo test --features 'clone nightly' || ! cargo test --features 'clone nightly' + - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features nightly; else ! cargo test --features nightly; fi + - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'clone nightly'; else ! cargo test --features 'clone nightly'; fi + - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'concurrent nightly'; else ! cargo test --features 'concurrent nightly'; fi + - if [[ "$(rustc --version)" =~ -(dev|nightly) ]]; then cargo test --features 'clone concurrent nightly'; else ! cargo test --features 'clone concurrent nightly'; fi - cargo test --features clone + - cargo test --features concurrent + - cargo test --features 'clone concurrent' - cargo test - cargo doc after_script: diff --git a/Cargo.toml b/Cargo.toml index 5ffe510..85f18cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ license = "MIT/Apache-2.0" [features] clone = [] +concurrent = [] nightly = [] diff --git a/README.md b/README.md index a815caf..a498edd 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,13 @@ Instructions Cargo all the way: it is `anymap` on crates.io. -There is an optional `clone` feature on the `anymap` crate; if enabled, your `AnyMap` will require contained types to implement `Clone` and will itself satisfy `Clone`. +There are a couple of optional features on the `anymap` crate: + +- `clone`: if enabled, your `AnyMap` will require contained types to implement `Clone` and will itself satisfy `Clone`. + +- `concurrent`: if enabled, your `AnyMap` will require contained types to satisfy `Send` and `Sync` and will itself satisfy `Send` and `Sync`. + +These can be combined if desired. For users of the nightly instead of the beta of rustc there are a couple of things behind the `nightly` feature like a `drain` method on the `RawAnyMap` and a more efficient hashing technique which makes lookup in the map a tad faster. diff --git a/src/lib.rs b/src/lib.rs index 9c0ff30..d32af5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,8 +85,6 @@ macro_rules! impl_common_methods { mod unchecked_any; pub mod raw; -#[cfg(feature = "clone")] -mod with_clone; /// A collection containing zero or one values for any given type and allowing convenient, /// type-safe access to those values. @@ -402,4 +400,11 @@ mod tests { assert_eq!(map2.get::(), Some(&F(5))); assert_eq!(map2.get::(), Some(&J(6))); } + + #[cfg(feature = "concurrent")] + #[test] + fn test_concurrent() { + fn assert_concurrent() { } + assert_concurrent::(); + } } diff --git a/src/raw/any.rs b/src/raw/any.rs new file mode 100644 index 0000000..d908040 --- /dev/null +++ b/src/raw/any.rs @@ -0,0 +1,105 @@ +use std::fmt; +use std::any::Any as StdAny; + +#[cfg(feature = "clone")] +#[doc(hidden)] +pub trait CloneToAny { + /// Clone `self` into a new `Box` object. + fn clone_to_any(&self) -> Box; +} + +#[cfg(feature = "clone")] +impl CloneToAny for T { + fn clone_to_any(&self) -> Box { + Box::new(self.clone()) + } +} + +macro_rules! define_any { + (#[$m:meta] $t:item $i:item) => { + /// A type to emulate dynamic typing. + /// + /// Every suitable type with no non-`'static` references implements `Any`. See the + /// [`std::any` documentation](https://doc.rust-lang.org/std/any/index.html) for more + /// details on `Any` in general. + /// + /// This trait is not `std::any::Any` but rather a type extending that for this library’s + /// purposes; most specifically, there are a couple of Cargo features that can be enabled + /// which will alter the constraints of what comprises a suitable type: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + #[cfg_attr(feature = "clone", doc = " ")] + #[cfg_attr(not(feature = "clone"), doc = " ")] + /// + /// + /// + /// + #[cfg_attr(feature = "concurrent", doc = " ")] + #[cfg_attr(not(feature = "concurrent"), doc = " ")] + /// + /// + ///
Feature nameAdditional boundsEnabled in these docs?
cloneCloneYesNo
concurrentSend + SyncYesNo
+ #[$m] $t + #[$m] $i + } +} + +define_any! { + #[cfg(all(not(feature = "clone"), not(feature = "concurrent")))] + pub trait Any: StdAny { } + impl Any for T { } +} + +define_any! { + #[cfg(all(feature = "clone", not(feature = "concurrent")))] + pub trait Any: StdAny + CloneToAny { } + impl Any for T { } +} + +define_any! { + #[cfg(all(not(feature = "clone"), feature = "concurrent"))] + pub trait Any: StdAny + Send + Sync { } + impl Any for T { } +} + +define_any! { + #[cfg(all(feature = "clone", feature = "concurrent"))] + pub trait Any: StdAny + CloneToAny + Send + Sync { } + impl Any for T { } +} + +#[cfg(feature = "clone")] +impl Clone for Box { + fn clone(&self) -> Box { + (**self).clone_to_any() + } +} + +impl<'a> fmt::Debug for &'a Any { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("&Any") + } +} + +impl<'a> fmt::Debug for Box { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.pad("Box") + } +} diff --git a/src/raw.rs b/src/raw/mod.rs similarity index 99% rename from src/raw.rs rename to src/raw/mod.rs index 0ed8886..1ae1a6c 100644 --- a/src/raw.rs +++ b/src/raw/mod.rs @@ -18,10 +18,9 @@ use std::ops::{Index, IndexMut}; #[cfg(feature = "nightly")] use std::ptr; -#[cfg(not(feature = "clone"))] -pub use std::any::Any; -#[cfg(feature = "clone")] -pub use with_clone::Any; +pub use self::any::Any; + +mod any; #[cfg(feature = "nightly")] struct TypeIdHasher { diff --git a/src/with_clone.rs b/src/with_clone.rs deleted file mode 100644 index 7bdb5b0..0000000 --- a/src/with_clone.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::fmt; - -#[doc(hidden)] -pub trait CloneToAny { - /// Clone `self` into a new `Box` object. - fn clone_to_any(&self) -> Box; -} - -impl CloneToAny for T { - fn clone_to_any(&self) -> Box { - Box::new(self.clone()) - } -} - -#[doc(hidden)] -/// Pretty much just `std::any::Any + Clone`. -pub trait Any: ::std::any::Any + CloneToAny { } - -impl Any for T { } - -impl Clone for Box { - fn clone(&self) -> Box { - (**self).clone_to_any() - } -} - -impl<'a> fmt::Debug for &'a Any { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("&Any") - } -} - -impl<'a> fmt::Debug for Box { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("Box") - } -}