Skip to content

Commit

Permalink
Docs & cleanups for DynAccess improvements
Browse files Browse the repository at this point in the history
Clean up & document the changes from previous commit from #78.
  • Loading branch information
vorner committed Dec 25, 2022
1 parent 6a1b3b1 commit 7194930
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 18 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
* The `AccessConvert` wrapper is needed less often in practice (#77).

# 1.5.1

* bug: Insufficient synchronization on weak platforms (#76).
Expand Down
75 changes: 57 additions & 18 deletions src/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,6 @@ impl<T> Access<T> for dyn DynAccess<T> + '_ + Sync + Send {
}
}

// Should probably be moved to a more appropriate place / perhaps more extensively tested / etc
#[cfg(test)]
mod test {
use super::*;
fn _expect_access<T>(_: impl Access<T>) {}
fn _test1<T>(x: Box<dyn DynAccess<T> + '_>) {
_expect_access(x)
}
fn _test2<T>(x: Box<dyn DynAccess<T> + '_ + Send>) {
_expect_access(x)
}
fn _test3<T>(x: Box<dyn DynAccess<T> + '_ + Send + Sync>) {
_expect_access(x)
}
}

impl<T: RefCnt, S: Strategy<T>> Access<T> for ArcSwapAny<T, S> {
type Guard = Guard<T, S>;

Expand Down Expand Up @@ -246,8 +230,19 @@ where

/// [DynAccess] to [Access] wrapper.
///
/// A workaround to allow double-dyn mapping, since `Box<dyn DynAccess>` doesn't implement [Access]
/// and [Map] needs that.
/// In previous versions, `Box<dyn DynAccess>` didn't implement [Access], to use inside [Map] one
/// could use this wrapper. Since then, a way was found to solve it. In most cases, this wrapper is
/// no longer necessary.
///
/// This is left in place for two reasons:
/// * Backwards compatibility.
/// * Corner-cases not covered by the found solution. For example, trait inheritance in the form of
/// `Box<dyn SomeTrait>` where `SomeTrait: Access` doesn't work out of the box and still needs
/// this wrapper.
///
/// # Examples
///
/// The example is for the simple case (which is no longer needed, but may help as an inspiration).
///
/// ```rust
/// use std::sync::Arc;
Expand Down Expand Up @@ -502,4 +497,48 @@ mod tests {
a.store(Arc::new(Cfg { value: 42 }));
assert_eq!(42, *Access::load(&map));
}

// Compile tests for dynamic access
fn _expect_access<T>(_: impl Access<T>) {}

fn _dyn_access<T>(x: Box<dyn DynAccess<T> + '_>) {
_expect_access(x)
}

fn _dyn_access_send<T>(x: Box<dyn DynAccess<T> + '_ + Send>) {
_expect_access(x)
}

fn _dyn_access_send_sync<T>(x: Box<dyn DynAccess<T> + '_ + Send + Sync>) {
_expect_access(x)
}

#[test]
fn double_dyn_access_complex() {
struct Inner {
val: usize,
}

struct Middle {
inner: Inner,
}

struct Outer {
middle: Middle,
}

let outer = Arc::new(ArcSwap::from_pointee(Outer {
middle: Middle {
inner: Inner { val: 42 },
},
}));

let middle: Arc<dyn DynAccess<Middle>> =
Arc::new(Map::new(outer, |outer: &Outer| &outer.middle));
let inner: Arc<dyn DynAccess<Inner>> =
Arc::new(Map::new(middle, |middle: &Middle| &middle.inner));
// Damn. We have the DynAccess wrapper in scope and need to disambiguate the inner.load()
let guard = Access::load(&inner);
assert_eq!(42, guard.val);
}
}

0 comments on commit 7194930

Please sign in to comment.