@@ -7,6 +7,7 @@ use ndk::native_activity::NativeActivity;
7
7
use ndk:: native_window:: NativeWindow ;
8
8
use ndk_sys:: { AInputQueue , ANativeActivity , ANativeWindow , ARect } ;
9
9
use once_cell:: sync:: Lazy ;
10
+ use parking_lot:: { MappedRwLockReadGuard , RwLock , RwLockReadGuard } ;
10
11
use std:: ffi:: { CStr , CString } ;
11
12
use std:: fmt;
12
13
use std:: fs:: File ;
@@ -15,7 +16,7 @@ use std::ops::Deref;
15
16
use std:: os:: raw;
16
17
use std:: os:: unix:: prelude:: * ;
17
18
use std:: ptr:: NonNull ;
18
- use std:: sync:: { Arc , Condvar , Mutex , RwLock , RwLockReadGuard } ;
19
+ use std:: sync:: { Arc , Condvar , Mutex } ;
19
20
use std:: thread;
20
21
21
22
#[ cfg( feature = "logger" ) ]
@@ -67,7 +68,20 @@ pub fn native_activity() -> &'static NativeActivity {
67
68
unsafe { NATIVE_ACTIVITY . as_ref ( ) . unwrap ( ) }
68
69
}
69
70
70
- pub struct LockReadGuard < T : ?Sized + ' static > ( RwLockReadGuard < ' static , T > ) ;
71
+ pub struct LockReadGuard < T : ?Sized + ' static > ( MappedRwLockReadGuard < ' static , T > ) ;
72
+
73
+ impl < T > LockReadGuard < T > {
74
+ /// Transpose an [`Option`] wrapped inside a [`LockReadGuard`]
75
+ ///
76
+ /// This is a _read_ lock for which the contents can't change; hence allowing the user to only
77
+ /// check for [`None`] once and hold a lock containing `T` directly thereafter, without
78
+ /// subsequent infallible [`Option::unwrap()`]s.
79
+ fn from_wrapped_option ( wrapped : RwLockReadGuard < ' static , Option < T > > ) -> Option < Self > {
80
+ RwLockReadGuard :: try_map ( wrapped, Option :: as_ref)
81
+ . ok ( )
82
+ . map ( Self )
83
+ }
84
+ }
71
85
72
86
impl < T : ?Sized > Deref for LockReadGuard < T > {
73
87
type Target = T ;
@@ -102,8 +116,8 @@ impl<T: ?Sized + fmt::Display> fmt::Display for LockReadGuard<T> {
102
116
/// # Warning
103
117
/// This function accesses a `static` variable internally and must only be used if you are sure
104
118
/// there is exactly one version of `ndk_glue` in your dependency tree.
105
- pub fn native_window ( ) -> LockReadGuard < Option < NativeWindow > > {
106
- LockReadGuard ( NATIVE_WINDOW . read ( ) . unwrap ( ) )
119
+ pub fn native_window ( ) -> Option < LockReadGuard < NativeWindow > > {
120
+ LockReadGuard :: from_wrapped_option ( NATIVE_WINDOW . read ( ) )
107
121
}
108
122
109
123
/// Returns an [`InputQueue`] held inside a lock, preventing Android from freeing it immediately
@@ -117,14 +131,14 @@ pub fn native_window() -> LockReadGuard<Option<NativeWindow>> {
117
131
/// # Warning
118
132
/// This function accesses a `static` variable internally and must only be used if you are sure
119
133
/// there is exactly one version of `ndk_glue` in your dependency tree.
120
- pub fn input_queue ( ) -> LockReadGuard < Option < InputQueue > > {
121
- LockReadGuard ( INPUT_QUEUE . read ( ) . unwrap ( ) )
134
+ pub fn input_queue ( ) -> Option < LockReadGuard < InputQueue > > {
135
+ LockReadGuard :: from_wrapped_option ( INPUT_QUEUE . read ( ) )
122
136
}
123
137
124
138
/// This function accesses a `static` variable internally and must only be used if you are sure
125
139
/// there is exactly one version of `ndk_glue` in your dependency tree.
126
140
pub fn content_rect ( ) -> Rect {
127
- CONTENT_RECT . read ( ) . unwrap ( ) . clone ( )
141
+ CONTENT_RECT . read ( ) . clone ( )
128
142
}
129
143
130
144
static PIPE : Lazy < [ RawFd ; 2 ] > = Lazy :: new ( || {
@@ -345,7 +359,6 @@ unsafe extern "C" fn on_window_focus_changed(
345
359
unsafe extern "C" fn on_window_created ( activity : * mut ANativeActivity , window : * mut ANativeWindow ) {
346
360
NATIVE_WINDOW
347
361
. write ( )
348
- . unwrap ( )
349
362
. replace ( NativeWindow :: clone_from_ptr ( NonNull :: new ( window) . unwrap ( ) ) ) ;
350
363
wake ( activity, Event :: WindowCreated ) ;
351
364
}
@@ -369,7 +382,7 @@ unsafe extern "C" fn on_window_destroyed(
369
382
window : * mut ANativeWindow ,
370
383
) {
371
384
wake ( activity, Event :: WindowDestroyed ) ;
372
- let mut native_window_guard = NATIVE_WINDOW . write ( ) . unwrap ( ) ;
385
+ let mut native_window_guard = NATIVE_WINDOW . write ( ) ;
373
386
assert_eq ! ( native_window_guard. as_ref( ) . unwrap( ) . ptr( ) . as_ptr( ) , window) ;
374
387
native_window_guard. take ( ) ;
375
388
}
@@ -384,7 +397,7 @@ unsafe extern "C" fn on_input_queue_created(
384
397
// future code cleans it up and sets it back to `None` again.
385
398
let looper = locked_looper. as_ref ( ) . expect ( "Looper does not exist" ) ;
386
399
input_queue. attach_looper ( looper, NDK_GLUE_LOOPER_INPUT_QUEUE_IDENT ) ;
387
- INPUT_QUEUE . write ( ) . unwrap ( ) . replace ( input_queue) ;
400
+ INPUT_QUEUE . write ( ) . replace ( input_queue) ;
388
401
wake ( activity, Event :: InputQueueCreated ) ;
389
402
}
390
403
@@ -393,7 +406,7 @@ unsafe extern "C" fn on_input_queue_destroyed(
393
406
queue : * mut AInputQueue ,
394
407
) {
395
408
wake ( activity, Event :: InputQueueDestroyed ) ;
396
- let mut input_queue_guard = INPUT_QUEUE . write ( ) . unwrap ( ) ;
409
+ let mut input_queue_guard = INPUT_QUEUE . write ( ) ;
397
410
assert_eq ! ( input_queue_guard. as_ref( ) . unwrap( ) . ptr( ) . as_ptr( ) , queue) ;
398
411
let input_queue = InputQueue :: from_ptr ( NonNull :: new ( queue) . unwrap ( ) ) ;
399
412
input_queue. detach_looper ( ) ;
@@ -407,6 +420,6 @@ unsafe extern "C" fn on_content_rect_changed(activity: *mut ANativeActivity, rec
407
420
right : ( * rect) . right as _ ,
408
421
bottom : ( * rect) . bottom as _ ,
409
422
} ;
410
- * CONTENT_RECT . write ( ) . unwrap ( ) = rect;
423
+ * CONTENT_RECT . write ( ) = rect;
411
424
wake ( activity, Event :: ContentRectChanged ) ;
412
425
}
0 commit comments