Skip to main content

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}