Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework Event type to allow synchronized cleanup #121

Closed
wants to merge 1 commit into from

Conversation

maciejgodek
Copy link
Contributor

@maciejgodek maciejgodek commented Feb 9, 2021

Previously, NativeActivity callbacks returned immediately after dispatching an asynchronous Event to the user on a UNIX pipe. This made it impossible to handle destruction callbacks (on_native_window_destroyed, on_input_queue_destroyed) in a manner conforming with the Android docs, which state that all cleanup must be completed before the callback returns, cf. ANativeActivityCallbacks docs.

Therefore, some method of blocking and then notifying the callback had to be introduced. In order to accomplish this, I wrote a simple wrapper on a lockless queue (crossbeam_queue::SegQueue) and an eventfd object, which allows sending arbitrary Rust objects to the user while notifying the Android Looper in a manner preserving the source of the notification.

This enabled a different semantics of the Event type. Events now transfer ownership of various Android handles (e.g. NativeActivity, InputQueue) to the user. The user is responsible for hanging on to these handles. When a corresponding *Destroyed event is received, the user must ensure that they complete all cleanup before dropping the contained EventSyncGuard object. They must not touch the relevant handle afterwards.

Additionally, care is taken to prevent the user from obtaining a handle to a NativeWindow or an InputQueue after a corresponding *_destroyed callback has fired. In this case, the *Created event will deliver None and no corresponding *Destroyed event will be dispatched.

This is a somewhat significant change of the public API and there are ways to make it more similar to the current version or just more ergonomic. I'm open to discussing these, as well as any performance or synchronization concerns.

Previously, NativeActivity callbacks returned immediately
after dispatching an asynchronous Event to the user on a UNIX
pipe. This made it impossible to handle destruction events
(`onNativeWindowDestroyed`, `onInputQueueDestroyed`) in
a manner conforming to the Android docs, which state that
all cleanup must be completed *before* the callback returns,
cf. https://developer.android.com/ndk/reference/struct/a-native-activity-callbacks#struct_a_native_activity_callbacks_1a6aaafbbfae4c0ac066b9d61ebb3ab97f

Therefore, some method of blocking and then notifying the callback
thread had to be introduced. In order to accomplish this, I wrote
a simple wrapper on a lockless queue (`crossbeam_queue::SegQueue`)
and an `eventfd` object, which allows sending arbitrary Rust
objects to the user while notifying the Android `Looper` in a
manner preserving the source of the notification.

This in turn enabled a different semantics of the `Event` type.
`Events` now transfer ownership of various Android handles
(e.g. `NativeActivity`, `InputQueue`) to the user. The user is
responsible for storing these handles. When a corresponding
`*Destroyed` event is received, the user must ensure that they
complete all cleanup before dropping the contained `EventSyncGuard`
object and do not touch the relevant handle afterwards.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant