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 {
20                // SAFETY: ffi::apple_log_os_atomic_i32_new is a thin wrapper that
21                // returns a non-null OSAtomicI32 handle. It is safe to call and always
22                // returns a valid pointer from the Swift bridge.
23                ffi::apple_log_os_atomic_i32_new(value)
24            })
25            .expect("Swift bridge never returns NULL for OSAtomicI32::new"),
26        }
27    }
28
29    #[must_use]
30    pub fn load(&self) -> i32 {
31        unsafe {
32            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
33            // This is a read-only atomic load operation.
34            ffi::apple_log_os_atomic_i32_load(self.ptr.as_ptr())
35        }
36    }
37
38    pub fn store(&self, value: i32) {
39        unsafe {
40            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
41            // This is an atomic store operation.
42            ffi::apple_log_os_atomic_i32_store(self.ptr.as_ptr(), value);
43        }
44    }
45
46    pub fn add(&self, amount: i32) -> i32 {
47        unsafe {
48            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
49            // This is an atomic add operation.
50            ffi::apple_log_os_atomic_i32_add(self.ptr.as_ptr(), amount)
51        }
52    }
53    pub fn add_barrier(&self, amount: i32) -> i32 {
54        unsafe {
55            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
56            // This is an atomic add with memory barrier operation.
57            ffi::apple_log_os_atomic_i32_add_barrier(self.ptr.as_ptr(), amount)
58        }
59    }
60    pub fn increment(&self) -> i32 {
61        unsafe {
62            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
63            // This is an atomic increment operation.
64            ffi::apple_log_os_atomic_i32_increment(self.ptr.as_ptr())
65        }
66    }
67    pub fn increment_barrier(&self) -> i32 {
68        unsafe {
69            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
70            // This is an atomic increment with memory barrier operation.
71            ffi::apple_log_os_atomic_i32_increment_barrier(self.ptr.as_ptr())
72        }
73    }
74    pub fn decrement(&self) -> i32 {
75        unsafe {
76            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
77            // This is an atomic decrement operation.
78            ffi::apple_log_os_atomic_i32_decrement(self.ptr.as_ptr())
79        }
80    }
81    pub fn decrement_barrier(&self) -> i32 {
82        unsafe {
83            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
84            // This is an atomic decrement with memory barrier operation.
85            ffi::apple_log_os_atomic_i32_decrement_barrier(self.ptr.as_ptr())
86        }
87    }
88    pub fn or(&self, mask: u32) -> i32 {
89        unsafe {
90            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
91            // This is an atomic bitwise OR operation.
92            ffi::apple_log_os_atomic_i32_or(self.ptr.as_ptr(), mask)
93        }
94    }
95    pub fn or_barrier(&self, mask: u32) -> i32 {
96        unsafe {
97            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
98            // This is an atomic bitwise OR with memory barrier operation.
99            ffi::apple_log_os_atomic_i32_or_barrier(self.ptr.as_ptr(), mask)
100        }
101    }
102    pub fn or_orig(&self, mask: u32) -> i32 {
103        unsafe {
104            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
105            // This is an atomic bitwise OR returning the original value.
106            ffi::apple_log_os_atomic_i32_or_orig(self.ptr.as_ptr(), mask)
107        }
108    }
109    pub fn or_orig_barrier(&self, mask: u32) -> i32 {
110        unsafe {
111            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
112            // This is an atomic bitwise OR with barrier returning the original value.
113            ffi::apple_log_os_atomic_i32_or_orig_barrier(self.ptr.as_ptr(), mask)
114        }
115    }
116    pub fn and(&self, mask: u32) -> i32 {
117        unsafe {
118            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
119            // This is an atomic bitwise AND operation.
120            ffi::apple_log_os_atomic_i32_and(self.ptr.as_ptr(), mask)
121        }
122    }
123    pub fn and_barrier(&self, mask: u32) -> i32 {
124        unsafe {
125            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
126            // This is an atomic bitwise AND with memory barrier operation.
127            ffi::apple_log_os_atomic_i32_and_barrier(self.ptr.as_ptr(), mask)
128        }
129    }
130    pub fn and_orig(&self, mask: u32) -> i32 {
131        unsafe {
132            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
133            // This is an atomic bitwise AND returning the original value.
134            ffi::apple_log_os_atomic_i32_and_orig(self.ptr.as_ptr(), mask)
135        }
136    }
137    pub fn and_orig_barrier(&self, mask: u32) -> i32 {
138        unsafe {
139            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
140            // This is an atomic bitwise AND with barrier returning the original value.
141            ffi::apple_log_os_atomic_i32_and_orig_barrier(self.ptr.as_ptr(), mask)
142        }
143    }
144    pub fn xor(&self, mask: u32) -> i32 {
145        unsafe {
146            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
147            // This is an atomic bitwise XOR operation.
148            ffi::apple_log_os_atomic_i32_xor(self.ptr.as_ptr(), mask)
149        }
150    }
151    pub fn xor_barrier(&self, mask: u32) -> i32 {
152        unsafe {
153            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
154            // This is an atomic bitwise XOR with memory barrier operation.
155            ffi::apple_log_os_atomic_i32_xor_barrier(self.ptr.as_ptr(), mask)
156        }
157    }
158    pub fn xor_orig(&self, mask: u32) -> i32 {
159        unsafe {
160            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
161            // This is an atomic bitwise XOR returning the original value.
162            ffi::apple_log_os_atomic_i32_xor_orig(self.ptr.as_ptr(), mask)
163        }
164    }
165    pub fn xor_orig_barrier(&self, mask: u32) -> i32 {
166        unsafe {
167            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
168            // This is an atomic bitwise XOR with barrier returning the original value.
169            ffi::apple_log_os_atomic_i32_xor_orig_barrier(self.ptr.as_ptr(), mask)
170        }
171    }
172    pub fn compare_and_swap(&self, old_value: i32, new_value: i32) -> bool {
173        unsafe {
174            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
175            // This is an atomic compare-and-swap operation.
176            ffi::apple_log_os_atomic_i32_compare_and_swap(self.ptr.as_ptr(), old_value, new_value)
177        }
178    }
179    pub fn compare_and_swap_barrier(&self, old_value: i32, new_value: i32) -> bool {
180        unsafe {
181            // SAFETY: self.ptr is a valid non-null OSAtomicI32 pointer.
182            // This is an atomic compare-and-swap with memory barrier operation.
183            ffi::apple_log_os_atomic_i32_compare_and_swap_barrier(
184                self.ptr.as_ptr(),
185                old_value,
186                new_value,
187            )
188        }
189    }
190}
191
192impl Drop for OSAtomicI32 {
193    fn drop(&mut self) {
194        unsafe { ffi::apple_log_os_atomic_i32_release(self.ptr.as_ptr()) };
195    }
196}
197
198/// Safe wrapper around a 64-bit legacy `OSAtomic` value.
199pub struct OSAtomicI64 {
200    ptr: NonNull<c_void>,
201}
202
203impl OSAtomicI64 {
204    #[must_use]
205    pub fn new(value: i64) -> Self {
206        Self {
207            ptr: NonNull::new(unsafe { ffi::apple_log_os_atomic_i64_new(value) })
208                .expect("Swift bridge never returns NULL for OSAtomicI64::new"),
209        }
210    }
211
212    #[must_use]
213    pub fn load(&self) -> i64 {
214        unsafe { ffi::apple_log_os_atomic_i64_load(self.ptr.as_ptr()) }
215    }
216
217    pub fn store(&self, value: i64) {
218        unsafe { ffi::apple_log_os_atomic_i64_store(self.ptr.as_ptr(), value) };
219    }
220
221    pub fn add(&self, amount: i64) -> i64 {
222        unsafe { ffi::apple_log_os_atomic_i64_add(self.ptr.as_ptr(), amount) }
223    }
224    pub fn add_barrier(&self, amount: i64) -> i64 {
225        unsafe { ffi::apple_log_os_atomic_i64_add_barrier(self.ptr.as_ptr(), amount) }
226    }
227    pub fn increment(&self) -> i64 {
228        unsafe { ffi::apple_log_os_atomic_i64_increment(self.ptr.as_ptr()) }
229    }
230    pub fn increment_barrier(&self) -> i64 {
231        unsafe { ffi::apple_log_os_atomic_i64_increment_barrier(self.ptr.as_ptr()) }
232    }
233    pub fn decrement(&self) -> i64 {
234        unsafe { ffi::apple_log_os_atomic_i64_decrement(self.ptr.as_ptr()) }
235    }
236    pub fn decrement_barrier(&self) -> i64 {
237        unsafe { ffi::apple_log_os_atomic_i64_decrement_barrier(self.ptr.as_ptr()) }
238    }
239    pub fn compare_and_swap(&self, old_value: i64, new_value: i64) -> bool {
240        unsafe {
241            ffi::apple_log_os_atomic_i64_compare_and_swap(self.ptr.as_ptr(), old_value, new_value)
242        }
243    }
244    pub fn compare_and_swap_barrier(&self, old_value: i64, new_value: i64) -> bool {
245        unsafe {
246            ffi::apple_log_os_atomic_i64_compare_and_swap_barrier(
247                self.ptr.as_ptr(),
248                old_value,
249                new_value,
250            )
251        }
252    }
253}
254
255impl Drop for OSAtomicI64 {
256    fn drop(&mut self) {
257        unsafe { ffi::apple_log_os_atomic_i64_release(self.ptr.as_ptr()) };
258    }
259}
260
261/// Queue backed by `OSAtomicEnqueue` / `OSAtomicDequeue`.
262pub struct OSAtomicQueue {
263    ptr: NonNull<c_void>,
264}
265
266impl OSAtomicQueue {
267    /// Creates an empty queue.
268    ///
269    /// # Errors
270    ///
271    /// Returns an error if the bridge cannot allocate the queue.
272    pub fn new() -> Result<Self, LogError> {
273        let ptr = bridge_ptr_result("OSAtomicQueue::new", |error_out| unsafe {
274            ffi::apple_log_os_atomic_queue_new(error_out)
275        })?;
276        Ok(Self { ptr })
277    }
278
279    pub fn enqueue(&self, value: usize) {
280        unsafe { ffi::apple_log_os_atomic_queue_enqueue(self.ptr.as_ptr(), value) };
281    }
282
283    #[must_use]
284    pub fn dequeue(&self) -> Option<usize> {
285        let mut value = 0_usize;
286        unsafe { ffi::apple_log_os_atomic_queue_dequeue(self.ptr.as_ptr(), &mut value) }
287            .then_some(value)
288    }
289}
290
291impl Drop for OSAtomicQueue {
292    fn drop(&mut self) {
293        unsafe { ffi::apple_log_os_atomic_queue_release(self.ptr.as_ptr()) };
294    }
295}
296
297/// FIFO queue backed by `OSAtomicFifoEnqueue` / `OSAtomicFifoDequeue`.
298pub struct OSAtomicFifoQueue {
299    ptr: NonNull<c_void>,
300}
301
302impl OSAtomicFifoQueue {
303    /// Creates an empty FIFO queue.
304    ///
305    /// # Errors
306    ///
307    /// Returns an error if the bridge cannot allocate the queue.
308    pub fn new() -> Result<Self, LogError> {
309        let ptr = bridge_ptr_result("OSAtomicFifoQueue::new", |error_out| unsafe {
310            ffi::apple_log_os_atomic_fifo_queue_new(error_out)
311        })?;
312        Ok(Self { ptr })
313    }
314
315    pub fn enqueue(&self, value: usize) {
316        unsafe { ffi::apple_log_os_atomic_fifo_queue_enqueue(self.ptr.as_ptr(), value) };
317    }
318
319    #[must_use]
320    pub fn dequeue(&self) -> Option<usize> {
321        let mut value = 0_usize;
322        unsafe { ffi::apple_log_os_atomic_fifo_queue_dequeue(self.ptr.as_ptr(), &mut value) }
323            .then_some(value)
324    }
325}
326
327impl Drop for OSAtomicFifoQueue {
328    fn drop(&mut self) {
329        unsafe { ffi::apple_log_os_atomic_fifo_queue_release(self.ptr.as_ptr()) };
330    }
331}