@@ -51,7 +51,9 @@ use std::{borrow::Borrow, sync::Arc};
51
51
use anyhow:: bail;
52
52
use bytes:: Buf ;
53
53
54
- use crate :: { FfiDefault , MetadataBuffer , Result , RustBuffer , UnexpectedUniFFICallbackError } ;
54
+ use crate :: {
55
+ FfiDefault , Handle , MetadataBuffer , Result , RustBuffer , UnexpectedUniFFICallbackError ,
56
+ } ;
55
57
56
58
/// Generalized FFI conversions
57
59
///
@@ -351,6 +353,66 @@ pub trait ConvertError<UT>: Sized {
351
353
fn try_convert_unexpected_callback_error ( e : UnexpectedUniFFICallbackError ) -> Result < Self > ;
352
354
}
353
355
356
+ /// Manage handles for `Arc<Self>` instances
357
+ ///
358
+ /// Handles are used to manage objects that are passed across the FFI. They general usage is:
359
+ ///
360
+ /// * Rust creates an `Arc<>`
361
+ /// * Rust uses `new_handle` to create a handle that represents the Arc reference
362
+ /// * Rust passes the handle to the foreign code as a `u64`
363
+ /// * The foreign code passes the handle back to `Rust` to refer to the object:
364
+ /// * Handle are usually passed as borrowed values. When an FFI function inputs a handle as an
365
+ /// argument, the foreign code simply passes a copy of the `u64` to Rust, which calls `get_arc`
366
+ /// to get a new `Arc<>` clone for it.
367
+ /// * Handles are returned as owned values. When an FFI function returns a handle, the foreign
368
+ /// code either stops using the handle after returning it or calls `clone_handle` and returns
369
+ /// the clone. TODO: actually start doing this (#1797)
370
+ /// * Eventually the foreign code may destroy their handle by passing it into a "free" FFI
371
+ /// function. This functions input an owned handle and consume it.
372
+ ///
373
+ /// The foreign code also defines their own handles. These represent foreign objects that are
374
+ /// passed to Rust. Using foreign handles is essentially the same as above, but in reverse.
375
+ ///
376
+ /// Handles must always be `Send` and the objects they reference must always be `Sync`.
377
+ /// This means that it must be safe to send handles to other threads and use them there.
378
+ ///
379
+ /// Note: this only needs to be derived for unsized types, there's a blanket impl for `T: Sized`.
380
+ ///
381
+ /// ## Safety
382
+ ///
383
+ /// All traits are unsafe (implementing it requires `unsafe impl`) because we can't guarantee
384
+ /// that it's safe to pass your type out to foreign-language code and back again. Buggy
385
+ /// implementations of this trait might violate some assumptions made by the generated code,
386
+ /// or might not match with the corresponding code in the generated foreign-language bindings.
387
+ /// These traits should not be used directly, only in generated code, and the generated code should
388
+ /// have fixture tests to test that everything works correctly together.
389
+ /// `&T` using the Arc.
390
+ pub unsafe trait HandleAlloc < UT > {
391
+ /// Create a new handle for an Arc value
392
+ ///
393
+ /// Use this to lower an Arc into a handle value before passing it across the FFI.
394
+ /// The newly-created handle will have reference count = 1.
395
+ fn new_handle ( value : Arc < Self > ) -> Handle ;
396
+
397
+ /// Clone a handle
398
+ ///
399
+ /// This creates a new handle from an existing one.
400
+ /// It's used when the foreign code wants to pass back an owned handle and still keep a copy
401
+ /// for themselves.
402
+ fn clone_handle ( handle : Handle ) -> Handle ;
403
+
404
+ /// Get a clone of the `Arc<>` using a "borrowed" handle.
405
+ ///
406
+ /// Take care that the handle can not be destroyed between when it's passed and when
407
+ /// `get_arc()` is called. #1797 is a cautionary tale.
408
+ fn get_arc ( handle : Handle ) -> Arc < Self > {
409
+ Self :: consume_handle ( Self :: clone_handle ( handle) )
410
+ }
411
+
412
+ /// Consume a handle, getting back the initial `Arc<>`
413
+ fn consume_handle ( handle : Handle ) -> Arc < Self > ;
414
+ }
415
+
354
416
/// Derive FFI traits
355
417
///
356
418
/// This can be used to derive:
@@ -463,4 +525,46 @@ macro_rules! derive_ffi_traits {
463
525
}
464
526
}
465
527
} ;
528
+
529
+ ( impl $( <$( $generic: ident) ,* >) ? $( :: uniffi:: ) ? HandleAlloc <$ut: path> for $ty: ty $( where $( $where: tt) * ) ?) => {
530
+ unsafe impl $( <$( $generic) ,* >) * $crate:: HandleAlloc <$ut> for $ty $( where $( $where) * ) *
531
+ {
532
+ // To implement HandleAlloc for an unsized type, wrap it with a second Arc which
533
+ // converts the wide pointer into a normal pointer.
534
+
535
+ fn new_handle( value: :: std:: sync:: Arc <Self >) -> $crate:: Handle {
536
+ $crate:: Handle :: from_pointer( :: std:: sync:: Arc :: into_raw( :: std:: sync:: Arc :: new( value) ) )
537
+ }
538
+
539
+ fn clone_handle( handle: $crate:: Handle ) -> $crate:: Handle {
540
+ unsafe {
541
+ :: std:: sync:: Arc :: <:: std:: sync:: Arc <Self >>:: increment_strong_count( handle. as_pointer:: <:: std:: sync:: Arc <Self >>( ) ) ;
542
+ }
543
+ handle
544
+ }
545
+
546
+ fn consume_handle( handle: $crate:: Handle ) -> :: std:: sync:: Arc <Self > {
547
+ unsafe {
548
+ :: std:: sync:: Arc :: <Self >:: clone(
549
+ & std:: sync:: Arc :: <:: std:: sync:: Arc :: <Self >>:: from_raw( handle. as_pointer:: <:: std:: sync:: Arc <Self >>( ) )
550
+ )
551
+ }
552
+ }
553
+ }
554
+ } ;
555
+ }
556
+
557
+ unsafe impl < T : Sized , UT > HandleAlloc < UT > for T {
558
+ fn new_handle ( value : Arc < Self > ) -> Handle {
559
+ Handle :: from_pointer ( Arc :: into_raw ( value) )
560
+ }
561
+
562
+ fn clone_handle ( handle : Handle ) -> Handle {
563
+ unsafe { Arc :: increment_strong_count ( handle. as_pointer :: < T > ( ) ) } ;
564
+ handle
565
+ }
566
+
567
+ fn consume_handle ( handle : Handle ) -> Arc < Self > {
568
+ unsafe { Arc :: from_raw ( handle. as_pointer ( ) ) }
569
+ }
466
570
}
0 commit comments