pub struct Subscription<T: Clone + Send + Sync + 'static> { /* private fields */ }Expand description
A RAII guard for an observer subscription that automatically unsubscribes when dropped
This struct provides automatic cleanup for observer subscriptions using RAII (Resource
Acquisition Is Initialization) pattern. When a Subscription goes out of scope, its
Drop implementation automatically removes the associated observer from the property.
This eliminates the need for manual unsubscribe() calls and helps prevent resource
leaks in scenarios where observers might otherwise be forgotten.
§Type Requirements
The generic type T must implement the same traits as ObservableProperty<T>:
Clone: Required for observer notificationsSend: Required for transferring between threadsSync: Required for concurrent access from multiple threads'static: Required for observer callbacks that may outlive the original scope
§Examples
§Basic RAII Subscription
use observable_property::ObservableProperty;
use std::sync::Arc;
let property = ObservableProperty::new(0);
{
// Create subscription - observer is automatically registered
let _subscription = property.subscribe_with_subscription(Arc::new(|old, new| {
println!("Value changed: {} -> {}", old, new);
}))?;
property.set(42)?; // Observer is called: "Value changed: 0 -> 42"
// When _subscription goes out of scope here, observer is automatically removed
}
property.set(100)?; // No observer output - subscription was automatically cleaned up§Cross-Thread Subscription Management
use observable_property::ObservableProperty;
use std::sync::Arc;
use std::thread;
let property = Arc::new(ObservableProperty::new(0));
let property_clone = property.clone();
// Create subscription in main thread
let subscription = property.subscribe_with_subscription(Arc::new(|old, new| {
println!("Observed: {} -> {}", old, new);
}))?;
// Move subscription to another thread for cleanup
let handle = thread::spawn(move || {
// Subscription is still active here
let _ = property_clone.set(42); // Will trigger observer
// When subscription is dropped here (end of thread), observer is cleaned up
drop(subscription);
});
handle.join().unwrap();
// Observer is no longer active
property.set(100)?; // No output§Conditional Scoped Subscriptions
use observable_property::ObservableProperty;
use std::sync::Arc;
let counter = ObservableProperty::new(0);
let debug_mode = true;
if debug_mode {
let _debug_subscription = counter.subscribe_with_subscription(Arc::new(|old, new| {
println!("Debug: counter {} -> {}", old, new);
}))?;
counter.set(1)?; // Prints debug info
counter.set(2)?; // Prints debug info
// Debug subscription automatically cleaned up when exiting if block
}
counter.set(3)?; // No debug output (subscription was cleaned up)§Thread Safety
Like ObservableProperty itself, Subscription is thread-safe. It can be safely
sent between threads and the automatic cleanup will work correctly even if the
subscription is dropped from a different thread than where it was created.
Trait Implementations§
Source§impl<T: Clone + Send + Sync + 'static> Drop for Subscription<T>
impl<T: Clone + Send + Sync + 'static> Drop for Subscription<T>
Source§fn drop(&mut self)
fn drop(&mut self)
Automatically removes the associated observer when the subscription is dropped
This implementation provides automatic cleanup by removing the observer
from the property’s observer list when the Subscription goes out of scope.
§Error Handling
If the property’s lock is poisoned or inaccessible during cleanup, the error
is silently ignored using the let _ = ... pattern. This is intentional
because:
- Drop implementations should not panic
- If the property is poisoned, it’s likely unusable anyway
- There’s no meaningful way to handle cleanup errors in a destructor
§Thread Safety
This method is safe to call from any thread, even if the subscription was created on a different thread.