Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jhugman committed Jan 9, 2024
1 parent 3a5172c commit 50d74f0
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 13 deletions.
3 changes: 1 addition & 2 deletions docs/manual/src/kotlin/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ The generated Kotlin modules can be configured using a `uniffi.toml` configurati
| `custom_types` | | A map which controls how custom types are exposed to Kotlin. See the [custom types section of the manual](../udl/custom_types.md#custom-types-in-the-bindings-code)|
| `external_packages` | | A map of packages to be used for the specified external crates. The key is the Rust crate name, the value is the Kotlin package which will be used referring to types in that crate. See the [external types section of the manual](../udl/ext_types_external.md#kotlin)
| `android` | `false` | Used to toggle on Android specific optimizations
| `android_cleaner` | `android` | Use the [`android.system.SystemCleaner`](https://developer.android.com/reference/android/system/SystemCleaner) instead of [`java.lang.ref.Cleaner`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ref/Cleaner.html)

| `android_cleaner` | `android` | Use the [`android.system.SystemCleaner`](https://developer.android.com/reference/android/system/SystemCleaner) instead of [`java.lang.ref.Cleaner`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ref/Cleaner.html). Fallback in both instances is the one shipped with JNA.

## Example

Expand Down
24 changes: 13 additions & 11 deletions uniffi_bindgen/src/bindings/kotlin/templates/ObjectRuntime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
//
// * Given an `FFIObject` instance, calling code is expected to call the special
// `destroy` method in order to free it after use, either by calling it explicitly
// or by using a higher-level helper like the `use` method. Failing to do so will
// leak the underlying Rust struct.
// or by using a higher-level helper like the `use` method. Failing to do so risks
// leaking the underlying Rust struct.
//
// * We can't assume that calling code will do the right thing, and must be prepared
// to handle Kotlin method calls executing concurrently with or even after a call to
Expand All @@ -32,6 +32,14 @@
// the destructor has been called, and must never call the destructor more than once.
// Doing so may trigger memory unsafety.
//
// * To mitigate many of the risks of leaking memory and use-after-free unsafety, a `Cleaner`
// is implemented to call the destructor when the Kotlin object becomes unreachable.
// This is done in a background thread. This is not a panacea, and client code should be aware that
// 1. the thread may starve if some there are objects that have poorly performing
// `drop` methods or do significant work in their `drop` methods.
// 2. the thread is shared across the whole library. This can be tuned by using `android_cleaner = true`,
// or `android = true` in the [`kotlin` section of the `uniffi.toml` file](https://mozilla.github.io/uniffi-rs/kotlin/configuration.html).
//
// If we try to implement this with mutual exclusion on access to the pointer, there is the
// possibility of a race between a method call and a concurrent call to `destroy`:
//
Expand Down Expand Up @@ -73,21 +81,15 @@
// called *and* all in-flight method calls have completed, avoiding violating any of the expectations
// of the underlying Rust code.
//
// In the future we may be able to replace some of this with automatic finalization logic, such as using
// the new "Cleaner" functionality in Java 9. The above scheme has been designed to work even if `destroy` is
// invoked by garbage-collection machinery rather than by calling code (which by the way, it's apparently also
// possible for the JVM to finalize an object while there is an in-flight call to one of its methods [1],
// so there would still be some complexity here).
//
// A cleaner makes a better alternative to _not_ calling `destroy()` as
// This makes a cleaner a better alternative to _not_ calling `destroy()` as
// and when the object is finished with, but the abstraction is not perfect: if the Rust object's `drop`
// method is slow, and/or there are many objects to cleanup, and it's on a low end Android device, then the cleaner
// thread may be starved, and the app will leak memory.
//
// In this case, `destroy`ing manually may be a better solution.
//
// The cleaner can live side by side with the manual calling of `destroy`. In the order of preference, uniffi objects
// with Rust peers can be reclaimed:
// The cleaner can live side by side with the manual calling of `destroy`. In the order of responsiveness, uniffi objects
// with Rust peers are reclaimed:
//
// 1. By calling the `destroy` method of the object, which calls `rustObject.free()`. If that doesn't happen:
// 2. When the object becomes unreachable, AND the Cleaner thread gets to call `rustObject.free()`. If the thread is starved then:
Expand Down

0 comments on commit 50d74f0

Please sign in to comment.