Skip to main content

android_activity/
waker.rs

1use std::ptr::NonNull;
2
3#[cfg(doc)]
4use crate::AndroidApp;
5
6/// A means to wake up the main thread while it is blocked waiting for I/O
7pub struct AndroidAppWaker {
8    looper: NonNull<ndk_sys::ALooper>,
9}
10
11impl Clone for AndroidAppWaker {
12    fn clone(&self) -> Self {
13        unsafe { ndk_sys::ALooper_acquire(self.looper.as_ptr()) }
14        Self {
15            looper: self.looper,
16        }
17    }
18}
19
20impl Drop for AndroidAppWaker {
21    fn drop(&mut self) {
22        unsafe { ndk_sys::ALooper_release(self.looper.as_ptr()) }
23    }
24}
25
26unsafe impl Send for AndroidAppWaker {}
27unsafe impl Sync for AndroidAppWaker {}
28
29impl AndroidAppWaker {
30    /// Acquire a ref to a looper as a means to be able to wake up the event loop
31    ///
32    /// # Safety
33    ///
34    /// The `ALooper` pointer must be valid and not null.
35    pub(crate) unsafe fn new(looper: *mut ndk_sys::ALooper) -> Self {
36        assert!(!looper.is_null(), "looper pointer must not be null");
37        unsafe {
38            // Give the waker its own reference to the looper
39            ndk_sys::ALooper_acquire(looper);
40            AndroidAppWaker {
41                looper: NonNull::new_unchecked(looper),
42            }
43        }
44    }
45
46    /// Interrupts the main thread if it is blocked within [`AndroidApp::poll_events()`]
47    ///
48    /// If [`AndroidApp::poll_events()`] is interrupted it will invoke the poll
49    /// callback with a [PollEvent::Wake][wake_event] event.
50    ///
51    /// [wake_event]: crate::PollEvent::Wake
52    pub fn wake(&self) {
53        unsafe {
54            ndk_sys::ALooper_wake(self.looper.as_ptr());
55        }
56    }
57}