Skip to main content

apple_log/
os_atomic.rs

1#![allow(clippy::missing_panics_doc, clippy::must_use_candidate)]
2
3use core::ffi::c_void;
4use std::ptr::NonNull;
5
6use crate::bridge_support::bridge_ptr_result;
7use crate::error::LogError;
8use crate::ffi;
9
10/// Safe wrapper around a 32-bit legacy `OSAtomic` value.
11pub struct OSAtomicI32 {
12    ptr: NonNull<c_void>,
13}
14
15impl OSAtomicI32 {
16    #[must_use]
17    pub fn new(value: i32) -> Self {
18        Self {
19            ptr: NonNull::new(unsafe { ffi::apple_log_os_atomic_i32_new(value) })
20                .expect("Swift bridge never returns NULL for OSAtomicI32::new"),
21        }
22    }
23
24    #[must_use]
25    pub fn load(&self) -> i32 {
26        unsafe { ffi::apple_log_os_atomic_i32_load(self.ptr.as_ptr()) }
27    }
28
29    pub fn store(&self, value: i32) {
30        unsafe { ffi::apple_log_os_atomic_i32_store(self.ptr.as_ptr(), value) };
31    }
32
33    pub fn add(&self, amount: i32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_add(self.ptr.as_ptr(), amount) } }
34    pub fn add_barrier(&self, amount: i32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_add_barrier(self.ptr.as_ptr(), amount) } }
35    pub fn increment(&self) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_increment(self.ptr.as_ptr()) } }
36    pub fn increment_barrier(&self) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_increment_barrier(self.ptr.as_ptr()) } }
37    pub fn decrement(&self) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_decrement(self.ptr.as_ptr()) } }
38    pub fn decrement_barrier(&self) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_decrement_barrier(self.ptr.as_ptr()) } }
39    pub fn or(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_or(self.ptr.as_ptr(), mask) } }
40    pub fn or_barrier(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_or_barrier(self.ptr.as_ptr(), mask) } }
41    pub fn or_orig(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_or_orig(self.ptr.as_ptr(), mask) } }
42    pub fn or_orig_barrier(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_or_orig_barrier(self.ptr.as_ptr(), mask) } }
43    pub fn and(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_and(self.ptr.as_ptr(), mask) } }
44    pub fn and_barrier(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_and_barrier(self.ptr.as_ptr(), mask) } }
45    pub fn and_orig(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_and_orig(self.ptr.as_ptr(), mask) } }
46    pub fn and_orig_barrier(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_and_orig_barrier(self.ptr.as_ptr(), mask) } }
47    pub fn xor(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_xor(self.ptr.as_ptr(), mask) } }
48    pub fn xor_barrier(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_xor_barrier(self.ptr.as_ptr(), mask) } }
49    pub fn xor_orig(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_xor_orig(self.ptr.as_ptr(), mask) } }
50    pub fn xor_orig_barrier(&self, mask: u32) -> i32 { unsafe { ffi::apple_log_os_atomic_i32_xor_orig_barrier(self.ptr.as_ptr(), mask) } }
51    pub fn compare_and_swap(&self, old_value: i32, new_value: i32) -> bool {
52        unsafe { ffi::apple_log_os_atomic_i32_compare_and_swap(self.ptr.as_ptr(), old_value, new_value) }
53    }
54    pub fn compare_and_swap_barrier(&self, old_value: i32, new_value: i32) -> bool {
55        unsafe {
56            ffi::apple_log_os_atomic_i32_compare_and_swap_barrier(
57                self.ptr.as_ptr(),
58                old_value,
59                new_value,
60            )
61        }
62    }
63}
64
65impl Drop for OSAtomicI32 {
66    fn drop(&mut self) {
67        unsafe { ffi::apple_log_os_atomic_i32_release(self.ptr.as_ptr()) };
68    }
69}
70
71/// Safe wrapper around a 64-bit legacy `OSAtomic` value.
72pub struct OSAtomicI64 {
73    ptr: NonNull<c_void>,
74}
75
76impl OSAtomicI64 {
77    #[must_use]
78    pub fn new(value: i64) -> Self {
79        Self {
80            ptr: NonNull::new(unsafe { ffi::apple_log_os_atomic_i64_new(value) })
81                .expect("Swift bridge never returns NULL for OSAtomicI64::new"),
82        }
83    }
84
85    #[must_use]
86    pub fn load(&self) -> i64 {
87        unsafe { ffi::apple_log_os_atomic_i64_load(self.ptr.as_ptr()) }
88    }
89
90    pub fn store(&self, value: i64) {
91        unsafe { ffi::apple_log_os_atomic_i64_store(self.ptr.as_ptr(), value) };
92    }
93
94    pub fn add(&self, amount: i64) -> i64 { unsafe { ffi::apple_log_os_atomic_i64_add(self.ptr.as_ptr(), amount) } }
95    pub fn add_barrier(&self, amount: i64) -> i64 { unsafe { ffi::apple_log_os_atomic_i64_add_barrier(self.ptr.as_ptr(), amount) } }
96    pub fn increment(&self) -> i64 { unsafe { ffi::apple_log_os_atomic_i64_increment(self.ptr.as_ptr()) } }
97    pub fn increment_barrier(&self) -> i64 { unsafe { ffi::apple_log_os_atomic_i64_increment_barrier(self.ptr.as_ptr()) } }
98    pub fn decrement(&self) -> i64 { unsafe { ffi::apple_log_os_atomic_i64_decrement(self.ptr.as_ptr()) } }
99    pub fn decrement_barrier(&self) -> i64 { unsafe { ffi::apple_log_os_atomic_i64_decrement_barrier(self.ptr.as_ptr()) } }
100    pub fn compare_and_swap(&self, old_value: i64, new_value: i64) -> bool {
101        unsafe { ffi::apple_log_os_atomic_i64_compare_and_swap(self.ptr.as_ptr(), old_value, new_value) }
102    }
103    pub fn compare_and_swap_barrier(&self, old_value: i64, new_value: i64) -> bool {
104        unsafe {
105            ffi::apple_log_os_atomic_i64_compare_and_swap_barrier(
106                self.ptr.as_ptr(),
107                old_value,
108                new_value,
109            )
110        }
111    }
112}
113
114impl Drop for OSAtomicI64 {
115    fn drop(&mut self) {
116        unsafe { ffi::apple_log_os_atomic_i64_release(self.ptr.as_ptr()) };
117    }
118}
119
120/// Queue backed by `OSAtomicEnqueue` / `OSAtomicDequeue`.
121pub struct OSAtomicQueue {
122    ptr: NonNull<c_void>,
123}
124
125impl OSAtomicQueue {
126    /// Creates an empty queue.
127    ///
128    /// # Errors
129    ///
130    /// Returns an error if the bridge cannot allocate the queue.
131    pub fn new() -> Result<Self, LogError> {
132        let ptr = bridge_ptr_result("OSAtomicQueue::new", |error_out| unsafe {
133            ffi::apple_log_os_atomic_queue_new(error_out)
134        })?;
135        Ok(Self { ptr })
136    }
137
138    pub fn enqueue(&self, value: usize) {
139        unsafe { ffi::apple_log_os_atomic_queue_enqueue(self.ptr.as_ptr(), value) };
140    }
141
142    #[must_use]
143    pub fn dequeue(&self) -> Option<usize> {
144        let mut value = 0_usize;
145        unsafe { ffi::apple_log_os_atomic_queue_dequeue(self.ptr.as_ptr(), &mut value) }.then_some(value)
146    }
147}
148
149impl Drop for OSAtomicQueue {
150    fn drop(&mut self) {
151        unsafe { ffi::apple_log_os_atomic_queue_release(self.ptr.as_ptr()) };
152    }
153}
154
155/// FIFO queue backed by `OSAtomicFifoEnqueue` / `OSAtomicFifoDequeue`.
156pub struct OSAtomicFifoQueue {
157    ptr: NonNull<c_void>,
158}
159
160impl OSAtomicFifoQueue {
161    /// Creates an empty FIFO queue.
162    ///
163    /// # Errors
164    ///
165    /// Returns an error if the bridge cannot allocate the queue.
166    pub fn new() -> Result<Self, LogError> {
167        let ptr = bridge_ptr_result("OSAtomicFifoQueue::new", |error_out| unsafe {
168            ffi::apple_log_os_atomic_fifo_queue_new(error_out)
169        })?;
170        Ok(Self { ptr })
171    }
172
173    pub fn enqueue(&self, value: usize) {
174        unsafe { ffi::apple_log_os_atomic_fifo_queue_enqueue(self.ptr.as_ptr(), value) };
175    }
176
177    #[must_use]
178    pub fn dequeue(&self) -> Option<usize> {
179        let mut value = 0_usize;
180        unsafe { ffi::apple_log_os_atomic_fifo_queue_dequeue(self.ptr.as_ptr(), &mut value) }
181            .then_some(value)
182    }
183}
184
185impl Drop for OSAtomicFifoQueue {
186    fn drop(&mut self) {
187        unsafe { ffi::apple_log_os_atomic_fifo_queue_release(self.ptr.as_ptr()) };
188    }
189}