scion_stack/types.rs
1// Copyright 2025 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! Common SCION stack types.
15
16use std::{
17 future::Future,
18 sync::{Arc, RwLock, Weak},
19};
20
21/// A future that resolves to a Result.
22pub trait ResFut<'a, R, E>: Future<Output = Result<R, E>> + Send + 'a {}
23impl<'a, R, E, T: Future<Output = Result<R, E>> + Send + 'a> ResFut<'a, R, E> for T {}
24
25/// A list of subscribers held as weak references.
26///
27/// This type is useful for implementing observer/listener patterns where:
28/// - Subscribers register to receive notifications
29/// - The registry doesn't keep subscribers alive (weak references)
30/// - Dead subscribers are cleaned up during registration
31///
32/// # Example
33///
34/// ```
35/// use std::sync::Arc;
36///
37/// use scion_stack::types::Subscribers;
38///
39/// trait EventReceiver: Send + Sync {
40/// fn on_event(&self, data: &str);
41/// }
42///
43/// struct MyReceiver;
44/// impl EventReceiver for MyReceiver {
45/// fn on_event(&self, data: &str) {
46/// println!("Received: {}", data);
47/// }
48/// }
49///
50/// let subscribers: Subscribers<dyn EventReceiver> = Subscribers::new();
51/// let receiver: Arc<dyn EventReceiver> = Arc::new(MyReceiver);
52///
53/// subscribers.register(receiver.clone());
54///
55/// subscribers.for_each(|r| r.on_event("hello"));
56/// drop(receiver);
57/// ```
58pub struct Subscribers<T: ?Sized + Send + Sync + 'static> {
59 receivers: Arc<RwLock<Vec<Weak<T>>>>,
60}
61
62impl<T: ?Sized + Send + Sync + 'static> Clone for Subscribers<T> {
63 fn clone(&self) -> Self {
64 Self {
65 receivers: Arc::clone(&self.receivers),
66 }
67 }
68}
69
70impl<T: ?Sized + Send + Sync + 'static> Subscribers<T> {
71 /// Creates a new empty set of subscribers.
72 pub fn new() -> Self {
73 Self {
74 receivers: Arc::new(RwLock::new(vec![])),
75 }
76 }
77
78 /// Register a subscriber. The subscriber is held as a weak reference
79 /// and will be automatically removed when dropped.
80 pub fn register(&self, subscriber: Arc<T>) {
81 let weak = Arc::downgrade(&subscriber);
82 let mut receivers = self.receivers.write().expect("lock poisoned");
83 // Remove dead weak references while we're at it
84 receivers.retain(|r| r.strong_count() > 0);
85 receivers.push(weak);
86 }
87
88 /// Execute a closure for each live subscriber.
89 pub fn for_each(&self, mut f: impl FnMut(&T)) {
90 let receivers = self.receivers.read().expect("lock poisoned");
91 for receiver in receivers.iter() {
92 if let Some(receiver) = receiver.upgrade() {
93 f(&*receiver);
94 }
95 }
96 }
97}
98
99impl<T: ?Sized + Send + Sync + 'static> Default for Subscribers<T> {
100 fn default() -> Self {
101 Self::new()
102 }
103}