Skip to main content

Handle

Struct Handle 

Source
pub struct Handle<T, V = T> { /* private fields */ }
Expand description

A clonable handle that can be used to remotely execute a closure on the corresponding [Actor].

Handles are the primary way to interact with actors. Clone them freely to share access across tasks. For read-only access, see ReadHandle. For local synchronization, see Cache. For rate-limited updates, see Throttle.

The second type parameter V is the broadcast type. By default V = T, meaning the actor broadcasts clones of itself. To broadcast a different type, implement BroadcastAs<V> and specify V explicitly (e.g. Handle::<MyType, Summary>::new(val)).

Implementations§

Source§

impl<T, V> Handle<T, V>
where T: BroadcastAs<V> + Send + Sync + 'static, V: Clone + Send + Sync + 'static,

Source

pub fn new(val: T) -> Handle<T, V>

Creates a new Handle and spawns the corresponding [Actor].

For Clone types, V defaults to T — the actor broadcasts clones of itself and you can simply write Handle::new(val).

For non-Clone types (or to broadcast a lightweight summary), implement BroadcastAs<V> and specify V explicitly:

#[derive(Clone, Debug, PartialEq)]
struct Size(usize);

impl BroadcastAs<Size> for Vec<u8> {
    fn to_broadcast(&self) -> Size { Size(self.len()) }
}

let handle: Handle<Vec<u8>, Size> = Handle::new(vec![1, 2, 3]);
let mut rx = handle.subscribe();
Source

pub fn new_throttled<C, F>( val: T, client: C, call: fn(&C, F), freq: Frequency, ) -> Handle<T, V>
where C: Send + Sync + 'static, V: Throttled<F>, F: Clone + Send + Sync + 'static,

Creates a new Handle and initializes a corresponding Throttle. The throttle fires given a specified Frequency. See Handle::spawn_throttle for an example.

Source§

impl<T, V> Handle<T, V>

Source

pub fn subscribe(&self) -> Receiver<V>

Returns a tokio::sync::broadcast::Receiver that receives all broadcasted values. Note that the inner value might not actually have changed. It broadcasts on any method that has a mutable reference to the actor.

§Examples
let handle = Handle::new(None);
let mut rx = handle.subscribe();
handle.set(Some("testing!")).await;
assert_eq!(rx.recv().await.unwrap(), Some("testing!"));
Source

pub fn get_read_handle(&self) -> ReadHandle<T, V>

Returns a ReadHandle that provides read-only access to this actor.

Source§

impl<T: Send + Sync + 'static, V> Handle<T, V>

Source

pub fn capacity(&self) -> usize

Returns the current capacity of the channel.

Source

pub async fn set(&self, val: T)

Overwrites the inner value of the actor with the new value. Broadcasts the new value to all subscribers.

§Examples
let handle = Handle::new(None);
handle.set(Some(1)).await;
assert_eq!(handle.get().await, Some(1));
Source

pub async fn set_if_changed(&self, val: T)
where T: PartialEq,

Overwrites the inner value, but only broadcasts if it actually changed.

§Examples
let handle = Handle::new(1);
let mut rx = handle.subscribe();
handle.set_if_changed(1).await; // Same value, no broadcast
handle.set_if_changed(2).await; // Different value, broadcasts
assert_eq!(rx.recv().await.unwrap(), 2);
Source

pub async fn with<R, F>(&self, f: F) -> R
where F: FnOnce(&T) -> R + Send + 'static, R: Send + 'static,

Runs a read-only closure on the actor’s value and returns the result. Does not broadcast.

This is useful for reading parts of the actor state without cloning the entire value, and works with non-Clone types.

§Examples
let handle = Handle::new(vec![1, 2, 3]);

// Extract just what you need, without cloning the whole Vec
let len = handle.with(|v| v.len()).await;
assert_eq!(len, 3);

let first = handle.with(|v| v.first().copied()).await;
assert_eq!(first, Some(1));
Source

pub async fn with_mut<R, F>(&self, f: F) -> R
where F: FnOnce(&mut T) -> R + Send + 'static, R: Send + 'static,

Runs a closure on the actor’s value mutably and returns the result.

This is useful for atomic read-modify-return operations without defining a dedicated #[actify] method.

Note: This always broadcasts after the closure returns, even if the closure did not actually mutate anything. Use Handle::with for read-only access that does not broadcast.

§Examples
let handle = Handle::new(vec![1, 2, 3]);
let mut rx = handle.subscribe();

// Mutate and return a result in one atomic operation
let popped = handle.with_mut(|v| v.pop()).await;
assert_eq!(popped, Some(3));
assert_eq!(handle.get().await, vec![1, 2]);

// The mutation triggered a broadcast
assert!(rx.try_recv().is_ok());
Source§

impl<T: Clone + Send + Sync + 'static, V> Handle<T, V>

Source

pub async fn get(&self) -> T

Receives a clone of the current value of the actor. Does not broadcast.

§Examples
let handle = Handle::new(1);
let result = handle.get().await;
assert_eq!(result, 1);
Source§

impl<T, V: Clone + Send + Sync + 'static> Handle<T, V>

Source

pub fn create_cache_from(&self, initial_value: V) -> Cache<V>

Creates a Cache initialized with the given value that locally synchronizes with broadcasted updates from the actor. As it is not initialized with the current value, any updates before construction are missed.

See also Handle::create_cache for a cache initialized with the current actor value, or Handle::create_cache_from_default to start from V::default().

§Examples
let handle = Handle::new(10);
let mut cache = handle.create_cache_from(42);
assert_eq!(cache.get_current(), &42);

handle.set(99).await;
assert_eq!(cache.get_newest(), &99);
Source§

impl<T, V: Default + Clone + Send + Sync + 'static> Handle<T, V>

Source

pub fn create_cache_from_default(&self) -> Cache<V>

Creates a Cache initialized with V::default() that locally synchronizes with broadcasted updates from the actor. As it is not initialized with the current value, any updates before construction are missed.

See also Handle::create_cache for a cache initialized with the current actor value, or Handle::create_cache_from to start from a custom value.

Source§

impl<T, V> Handle<T, V>
where T: Clone + BroadcastAs<V> + Send + Sync + 'static, V: Clone + Send + Sync + 'static,

Source

pub async fn create_cache(&self) -> Cache<V>

Creates an initialized Cache that locally synchronizes with the remote actor. As it is initialized with the current value, any updates before construction are included.

See also Handle::create_cache_from_default for a cache that starts from V::default().

Source

pub async fn spawn_throttle<C, F>( &self, client: C, call: fn(&C, F), freq: Frequency, )
where C: Send + Sync + 'static, V: Throttled<F>, F: Clone + Send + Sync + 'static,

Spawns a Throttle that fires given a specified Frequency.

The broadcast type must implement Throttled<F> to convert the value into the callback argument.

§Examples
struct Logger(Arc<Mutex<Vec<i32>>>);
impl Logger {
    fn log(&self, val: i32) { self.0.lock().unwrap().push(val); }
}

let handle = Handle::new(1);
let values = Arc::new(Mutex::new(Vec::new()));
handle.spawn_throttle(Logger(values.clone()), Logger::log, Frequency::OnEvent).await;

handle.set(2).await;
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
// Fires once with the current value on creation, then on each broadcast
assert_eq!(*values.lock().unwrap(), vec![1, 2]);

Trait Implementations§

Source§

impl<T, V> Clone for Handle<T, V>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, V> Debug for Handle<T, V>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Default + Clone + Send + Sync + 'static> Default for Handle<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<K, V, __V> HashMapHandle<K, V> for Handle<HashMap<K, V>, __V>
where K: Clone + Eq + Hash + Send + Sync + 'static, V: Clone + Send + Sync + 'static,

Extension methods for Handle<HashMap<K, V>>, exposed as HashMapHandle.

Source§

async fn get_key(&self, key: K) -> Option<V>

Returns a clone of the value corresponding to the key if it exists It is equivalent to the Hashmap get(), but the method name is changed to avoid conflicts with the get() method of the actor in general

§Examples
let handle = Handle::new(HashMap::new());
handle.insert("test", 10).await;
let res = handle.get_key("test").await;
assert_eq!(res, Some(10));
Source§

async fn insert(&self, key: K, val: V) -> Option<V>

Inserts a key-value pair into the map. If the map did not have this key present, None is returned. If the map did have this key present, the value is updated, and the old value is returned. In that case the key is not updated.

§Examples
let handle = Handle::new(HashMap::new());
let res = handle.insert("test", 10).await;
assert_eq!(res, None);

let old_value = handle.insert("test", 20).await;
assert_eq!(old_value, Some(10));
Source§

async fn remove(&self, key: K) -> Option<V>

Removes a key from the map, returning the value at the key if the key was previously in the map. Equivalent to HashMap::remove.

§Examples
let handle = Handle::new(HashMap::new());
handle.insert("test", 10).await;
let res = handle.remove("test").await;
assert_eq!(res, Some(10));

let res = handle.remove("test").await;
assert_eq!(res, None);
Source§

async fn clear(&self)

Clears the map, removing all key-value pairs. Equivalent to HashMap::clear.

§Examples
let handle = Handle::new(HashMap::new());
handle.insert("test", 10).await;
handle.clear().await;
assert!(handle.is_empty().await);
Source§

async fn is_empty(&self) -> bool

Returns true if the map contains no elements.

§Examples
let handle = Handle::new(HashMap::<&str, i32>::new());
assert!(handle.is_empty().await);
Source§

async fn keys(&self) -> Vec<K>

Returns a Vec of all keys in the map. Equivalent to HashMap::keys, but collected into a Vec.

§Examples
let handle = Handle::new(HashMap::new());
handle.insert("a", 1).await;
handle.insert("b", 2).await;
let mut keys = handle.keys().await;
keys.sort();
assert_eq!(keys, vec!["a", "b"]);
Source§

async fn values(&self) -> Vec<V>

Returns a Vec of all values in the map. Equivalent to HashMap::values, but collected into a Vec.

§Examples
let handle = Handle::new(HashMap::new());
handle.insert("a", 1).await;
handle.insert("b", 2).await;
let mut values = handle.values().await;
values.sort();
assert_eq!(values, vec![1, 2]);
Source§

impl<K, __V> HashSetHandle<K> for Handle<HashSet<K>, __V>
where K: Clone + Eq + Hash + Send + Sync + 'static,

Extension methods for Handle<HashSet<K>>, exposed as HashSetHandle.

Source§

async fn insert(&self, val: K) -> bool

Adds a value to the set. Returns whether the value was newly inserted. That is:

  • If the set did not previously contain this value, true is returned.
  • If the set already contained this value, false is returned, and the set is not modified: original value is not replaced, and the value passed as argument is dropped.
§Examples
let handle = Handle::new(HashSet::new());
let res = handle.insert(10).await;
assert!(res);

let res = handle.insert(10).await;
assert!(!res);
Source§

async fn is_empty(&self) -> bool

Returns true if the set contains no elements.

§Examples
let handle = Handle::new(HashSet::<i32>::new());
assert!(handle.is_empty().await);
Source§

impl<T, __V> OptionHandle<T> for Handle<Option<T>, __V>
where T: Clone + Send + Sync + 'static,

An implementation of the ActorOption extension trait for the standard Option. This extension trait is made available on the Handle through the actify macro as OptionHandle. Within the actor these methods are invoked, which in turn just extend the functionality provided by the std library.

Source§

async fn is_some(&self) -> bool

Returns true if the option is a Some value.

§Examples
let handle = Handle::new(Some(1));
assert!(handle.is_some().await);
Source§

async fn is_none(&self) -> bool

Returns true if the option is a None value.

§Examples
let handle = Handle::new(Option::<i32>::None);
assert!(handle.is_none().await);
Source§

impl<T, __V> VecHandle<T> for Handle<Vec<T>, __V>
where T: Clone + Send + Sync + 'static,

Extension methods for Handle<Vec<T>>, exposed as VecHandle.

Source§

async fn push(&self, value: T)

Appends an element to the back of a collection.

§Examples
let handle = Handle::new(vec![1, 2]);
handle.push(100).await;
assert_eq!(handle.get().await, vec![1, 2, 100]);
Source§

async fn is_empty(&self) -> bool

Returns true if the vector contains no elements.

§Examples
let handle = Handle::new(Vec::<i32>::new());
assert!(handle.is_empty().await);
Source§

async fn drain<R>(&self, range: R) -> Vec<T>
where R: RangeBounds<usize> + Send + Sync + 'static,

Removes the complete range from the vector in bulk, and returns it as a new vector

§Examples
let handle = Handle::new(vec![1, 2]);
let res = handle.drain(..).await;
assert_eq!(res, vec![1, 2]);
assert_eq!(handle.get().await, Vec::<i32>::new());

Auto Trait Implementations§

§

impl<T, V> Freeze for Handle<T, V>

§

impl<T, V = T> !RefUnwindSafe for Handle<T, V>

§

impl<T, V> Send for Handle<T, V>
where V: Send,

§

impl<T, V> Sync for Handle<T, V>
where V: Send,

§

impl<T, V> Unpin for Handle<T, V>

§

impl<T, V> UnsafeUnpin for Handle<T, V>

§

impl<T, V = T> !UnwindSafe for Handle<T, V>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> BroadcastAs<T> for T
where T: Clone,

Source§

fn to_broadcast(&self) -> T

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Throttled<T> for T
where T: Clone,

Source§

fn parse(&self) -> T

Implement this parse function on the type to be sent by the throttle
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.