pipewire/loop_/
rc.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4use std::{
5    ops::Deref,
6    ptr,
7    rc::{Rc, Weak},
8};
9
10use super::{Loop, LoopBox};
11use crate::Error;
12
13/// Trait implemented by objects that implement a `pw_loop` and are reference counted in some way.
14///
15/// # Safety
16///
17/// The [`Loop`] returned by the implementation of `AsRef<Loop>` must remain valid as long as any clone
18/// of the trait implementor is still alive.
19pub unsafe trait IsLoopRc: Clone + AsRef<Loop> + 'static {}
20
21#[derive(Debug)]
22struct LoopRcInner {
23    loop_: LoopBox,
24}
25
26/// Reference counting smart pointer providing shared ownership of a PipeWire [loop](super).
27///
28/// For the non-owning variant, see [`LoopWeak`].
29/// For unique ownership, see [`LoopBox`].
30///
31/// For an explanation of these, see [Smart pointers to PipeWire objects](crate#smart-pointers-to-pipewire-objects).
32#[derive(Clone, Debug)]
33pub struct LoopRc {
34    inner: Rc<LoopRcInner>,
35}
36
37impl LoopRc {
38    /// Create a new [`LoopRc`].
39    pub fn new(properties: Option<&spa::utils::dict::DictRef>) -> Result<Self, Error> {
40        let loop_ = LoopBox::new(properties)?;
41
42        Ok(Self {
43            inner: Rc::new(LoopRcInner { loop_ }),
44        })
45    }
46
47    /// Create a new [`LoopRc`] from a raw [`pw_loop`](`pw_sys::pw_loop`), taking ownership of it.
48    ///
49    /// # Safety
50    /// The provided pointer must point to a valid, well aligned [`pw_loop`](`pw_sys::pw_loop`).
51    ///
52    /// The raw loop should not be manually destroyed or moved, as the new [`LoopRc`] takes ownership of it.
53    pub unsafe fn from_raw(ptr: ptr::NonNull<pw_sys::pw_loop>) -> Self {
54        let loop_ = LoopBox::from_raw(ptr);
55
56        Self {
57            inner: Rc::new(LoopRcInner { loop_ }),
58        }
59    }
60
61    pub fn downgrade(&self) -> LoopWeak {
62        let weak = Rc::downgrade(&self.inner);
63        LoopWeak { weak }
64    }
65}
66
67// Safety: The inner pw_loop is guaranteed to remain valid while any clone of the `LoopRc` is held,
68//         because we use an internal Rc to keep it alive.
69unsafe impl IsLoopRc for LoopRc {}
70
71impl Deref for LoopRc {
72    type Target = Loop;
73
74    fn deref(&self) -> &Self::Target {
75        self.inner.loop_.deref()
76    }
77}
78
79impl std::convert::AsRef<Loop> for LoopRc {
80    fn as_ref(&self) -> &Loop {
81        self.deref()
82    }
83}
84
85/// Non-owning reference to a [loop](super) managed by [`LoopRc`].
86///
87/// The loop can be accessed by calling [`upgrade`](Self::upgrade).
88pub struct LoopWeak {
89    weak: Weak<LoopRcInner>,
90}
91
92impl LoopWeak {
93    pub fn upgrade(&self) -> Option<LoopRc> {
94        self.weak.upgrade().map(|inner| LoopRc { inner })
95    }
96}