[][src]Module async_coap::arc_guard

Arc Guard

This crate1 provides the ArcGuard class, which is a container for a single object with lifetime that is bound to that of an Arc. This is useful for passing around boxed futures that have a lifetime that is limited to that of the object that created it.

For example, the following does not compile:

This example deliberately fails to compile
use futures::{future::ready,future::BoxFuture,prelude::*};
use std::sync::{Arc,Weak};
use arc_guard::{ArcGuard,ArcGuardExt};

trait PropertyFetcher {
        fn fetch(
            &self,
            key: &str,
        ) -> BoxFuture<Option<String>>;
}

struct WeakFetcher {
    sub_obj: Weak<Box<PropertyFetcher>>,
}

impl PropertyFetcher for WeakFetcher {
    fn fetch(&self, key: &str) -> BoxFuture<Option<String>> {
        if let Some(arc) = self.sub_obj.upgrade() {
            // error[E0515]: cannot return value referencing local variable `arc`
            arc.fetch(key).boxed()
        } else {
            ready(None).boxed()
        }
    }
}

If you think about it, the fact that rustc doesn't like this code makes perfect sense: because sub_obj is a weak reference, it could be dropped at any moment, violating the lifetime guarantee for the return value of fetch(). To fix this, we need to ensure that the value we return internally keeps an Arc reference to the object that created it. That's where ArcGuard comes in:


impl PropertyFetcher for WeakFetcher {
    fn fetch(&self, key: &str) -> BoxFuture<Option<String>> {
        if let Some(arc) = self.sub_obj.upgrade() {
            // Compiles and works!
            arc.guard(|x|x.fetch(key)).boxed()
        } else {
            ready(None).boxed()
        }
    }
}

Additional Examples


let mut arc = Arc::new("foobar".to_string());

let guarded = arc.guard(|s| &s.as_str()[3..]);

assert_eq!(guarded, "bar");

// We can't get a mutable instance to the
// string while `guarded` is still around.
assert_eq!(Arc::get_mut(&mut arc), None);

core::mem::drop(guarded);

assert!(Arc::get_mut(&mut arc).is_some());

  1. I would have loved to call this crate lifeguard, because it is a "guard" on the lifetime of the contained "head" instance, but sadly that name was already taken

Structs

ArcGuard

A container for a single object with lifetime that is bound to that of an Arc.

Traits

ArcGuardExt

A convenience trait for Arc<> that makes it easier to construct ArcGuard<> instances.