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#[derive(Clone, Debug)]
27pub struct LoopRc {
28    inner: Rc<LoopRcInner>,
29}
30
31impl LoopRc {
32    /// Create a new [`LoopRc`].
33    pub fn new(properties: Option<&spa::utils::dict::DictRef>) -> Result<Self, Error> {
34        let loop_ = LoopBox::new(properties)?;
35
36        Ok(Self {
37            inner: Rc::new(LoopRcInner { loop_ }),
38        })
39    }
40
41    /// Create a new [`LoopRc`] from a raw [`pw_loop`](`pw_sys::pw_loop`), taking ownership of it.
42    ///
43    /// # Safety
44    /// The provided pointer must point to a valid, well aligned [`pw_loop`](`pw_sys::pw_loop`).
45    ///
46    /// The raw loop should not be manually destroyed or moved, as the new [`LoopRc`] takes ownership of it.
47    pub unsafe fn from_raw(ptr: ptr::NonNull<pw_sys::pw_loop>) -> Self {
48        let loop_ = LoopBox::from_raw(ptr);
49
50        Self {
51            inner: Rc::new(LoopRcInner { loop_ }),
52        }
53    }
54
55    pub fn downgrade(&self) -> LoopWeak {
56        let weak = Rc::downgrade(&self.inner);
57        LoopWeak { weak }
58    }
59}
60
61// Safety: The inner pw_loop is guaranteed to remain valid while any clone of the `LoopRc` is held,
62//         because we use an internal Rc to keep it alive.
63unsafe impl IsLoopRc for LoopRc {}
64
65impl Deref for LoopRc {
66    type Target = Loop;
67
68    fn deref(&self) -> &Self::Target {
69        self.inner.loop_.deref()
70    }
71}
72
73impl std::convert::AsRef<Loop> for LoopRc {
74    fn as_ref(&self) -> &Loop {
75        self.deref()
76    }
77}
78
79pub struct LoopWeak {
80    weak: Weak<LoopRcInner>,
81}
82
83impl LoopWeak {
84    pub fn upgrade(&self) -> Option<LoopRc> {
85        self.weak.upgrade().map(|inner| LoopRc { inner })
86    }
87}