libobs_wrapper/
unsafe_send.rs

1//! Sendable wrapper types for non-Send types
2//!
3//! This module provides wrapper types that allow non-Send types to be sent
4//! across thread boundaries. Use with caution - these are unsafe by design.
5
6use std::{hash::Hash, sync::Arc};
7
8use crate::utils::ObsDropGuard;
9
10#[derive(Debug, Clone)]
11pub struct Sendable<T>(pub T);
12
13#[cfg(feature = "enable_runtime")]
14unsafe impl<T> Send for Sendable<T> {}
15#[cfg(feature = "enable_runtime")]
16unsafe impl<T> Sync for Sendable<T> {}
17
18#[derive(Debug, Clone)]
19pub struct AlwaysSendable<T>(pub T);
20
21unsafe impl<T> Send for AlwaysSendable<T> {}
22unsafe impl<T> Sync for AlwaysSendable<T> {}
23
24#[derive(Debug, Hash, Clone, PartialEq, Eq)]
25pub struct SendableComp<T>(pub T);
26
27#[cfg(feature = "enable_runtime")]
28unsafe impl<T: PartialEq> Send for SendableComp<T> {}
29#[cfg(feature = "enable_runtime")]
30unsafe impl<T: PartialEq> Sync for SendableComp<T> {}
31
32#[derive(Debug, Clone)]
33/// Most of the time, this smart pointer will need to be the last field of a struct to ensure proper drop order.
34pub struct SmartPointerSendable<T: Clone> {
35    ptr: T,
36    drop_guard: Arc<dyn ObsDropGuard>,
37}
38
39impl<T: Clone> SmartPointerSendable<T> {
40    pub fn new(ptr: T, drop_guard: Arc<dyn ObsDropGuard>) -> Self {
41        Self { ptr, drop_guard }
42    }
43
44    pub fn get_ptr(&self) -> T {
45        self.ptr.clone()
46    }
47
48    pub fn into_comp(self) -> SmartPointerSendableComp<T> {
49        SmartPointerSendableComp::new(self.ptr, self.drop_guard)
50    }
51
52    /// # Safety
53    /// This exposes the drop guard, which may lead to misuse. Make sure to only use it when you need it.
54    pub unsafe fn drop_guard(&self) -> Arc<dyn ObsDropGuard> {
55        self.drop_guard.clone()
56    }
57}
58
59#[cfg(feature = "enable_runtime")]
60unsafe impl<T: Clone> Send for SmartPointerSendable<T> {}
61#[cfg(feature = "enable_runtime")]
62unsafe impl<T: Clone> Sync for SmartPointerSendable<T> {}
63
64#[derive(Debug, Clone)]
65pub struct SmartPointerSendableComp<T: Clone> {
66    ptr: T,
67    _drop_guard: Arc<dyn ObsDropGuard>,
68}
69
70impl<T> Hash for SmartPointerSendableComp<T>
71where
72    T: Clone + Hash,
73{
74    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
75        self.ptr.hash(state);
76    }
77}
78
79impl<T> PartialEq for SmartPointerSendableComp<T>
80where
81    T: Clone + PartialEq,
82{
83    fn eq(&self, other: &Self) -> bool {
84        self.ptr == other.ptr
85    }
86}
87
88impl<T> Eq for SmartPointerSendableComp<T> where T: Clone + Eq {}
89
90impl<T: Clone> SmartPointerSendableComp<T> {
91    pub fn new(ptr: T, drop_guard: Arc<dyn ObsDropGuard>) -> Self {
92        Self {
93            ptr,
94            _drop_guard: drop_guard,
95        }
96    }
97
98    pub fn get_ptr(&self) -> T {
99        self.ptr.clone()
100    }
101}
102
103#[cfg(feature = "enable_runtime")]
104unsafe impl<T: Clone> Send for SmartPointerSendableComp<T> {}
105#[cfg(feature = "enable_runtime")]
106unsafe impl<T: Clone> Sync for SmartPointerSendableComp<T> {}