@@ -6,8 +6,10 @@ use crate::init::{self, PinInit};
6
6
use alloc:: boxed:: Box ;
7
7
use core:: {
8
8
cell:: UnsafeCell ,
9
+ marker:: PhantomData ,
9
10
mem:: MaybeUninit ,
10
11
ops:: { Deref , DerefMut } ,
12
+ ptr:: NonNull ,
11
13
} ;
12
14
13
15
/// Used to transfer ownership to and from foreign (non-Rust) languages.
@@ -295,6 +297,111 @@ opaque_init_funcs! {
295
297
"Rust" manual_init4( arg1: A1 , arg2: A2 , arg3: A3 , arg4: A4 ) ;
296
298
}
297
299
300
+ /// Types that are _always_ reference counted.
301
+ ///
302
+ /// It allows such types to define their own custom ref increment and decrement functions.
303
+ /// Additionally, it allows users to convert from a shared reference `&T` to an owned reference
304
+ /// [`ARef<T>`].
305
+ ///
306
+ /// This is usually implemented by wrappers to existing structures on the C side of the code. For
307
+ /// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted
308
+ /// instances of a type.
309
+ ///
310
+ /// # Safety
311
+ ///
312
+ /// Implementers must ensure that increments to the reference count keep the object alive in memory
313
+ /// at least until matching decrements are performed.
314
+ ///
315
+ /// Implementers must also ensure that all instances are reference-counted. (Otherwise they
316
+ /// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object
317
+ /// alive.)
318
+ pub unsafe trait AlwaysRefCounted {
319
+ /// Increments the reference count on the object.
320
+ fn inc_ref ( & self ) ;
321
+
322
+ /// Decrements the reference count on the object.
323
+ ///
324
+ /// Frees the object when the count reaches zero.
325
+ ///
326
+ /// # Safety
327
+ ///
328
+ /// Callers must ensure that there was a previous matching increment to the reference count,
329
+ /// and that the object is no longer used after its reference count is decremented (as it may
330
+ /// result in the object being freed), unless the caller owns another increment on the refcount
331
+ /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls
332
+ /// [`AlwaysRefCounted::dec_ref`] once).
333
+ unsafe fn dec_ref ( obj : NonNull < Self > ) ;
334
+ }
335
+
336
+ /// An owned reference to an always-reference-counted object.
337
+ ///
338
+ /// The object's reference count is automatically decremented when an instance of [`ARef`] is
339
+ /// dropped. It is also automatically incremented when a new instance is created via
340
+ /// [`ARef::clone`].
341
+ ///
342
+ /// # Invariants
343
+ ///
344
+ /// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In
345
+ /// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.
346
+ pub struct ARef < T : AlwaysRefCounted > {
347
+ ptr : NonNull < T > ,
348
+ _p : PhantomData < T > ,
349
+ }
350
+
351
+ impl < T : AlwaysRefCounted > ARef < T > {
352
+ /// Creates a new instance of [`ARef`].
353
+ ///
354
+ /// It takes over an increment of the reference count on the underlying object.
355
+ ///
356
+ /// # Safety
357
+ ///
358
+ /// Callers must ensure that the reference count was incremented at least once, and that they
359
+ /// are properly relinquishing one increment. That is, if there is only one increment, callers
360
+ /// must not use the underlying object anymore -- it is only safe to do so via the newly
361
+ /// created [`ARef`].
362
+ pub unsafe fn from_raw ( ptr : NonNull < T > ) -> Self {
363
+ // INVARIANT: The safety requirements guarantee that the new instance now owns the
364
+ // increment on the refcount.
365
+ Self {
366
+ ptr,
367
+ _p : PhantomData ,
368
+ }
369
+ }
370
+ }
371
+
372
+ impl < T : AlwaysRefCounted > Clone for ARef < T > {
373
+ fn clone ( & self ) -> Self {
374
+ self . inc_ref ( ) ;
375
+ // SAFETY: We just incremented the refcount above.
376
+ unsafe { Self :: from_raw ( self . ptr ) }
377
+ }
378
+ }
379
+
380
+ impl < T : AlwaysRefCounted > Deref for ARef < T > {
381
+ type Target = T ;
382
+
383
+ fn deref ( & self ) -> & Self :: Target {
384
+ // SAFETY: The type invariants guarantee that the object is valid.
385
+ unsafe { self . ptr . as_ref ( ) }
386
+ }
387
+ }
388
+
389
+ impl < T : AlwaysRefCounted > From < & T > for ARef < T > {
390
+ fn from ( b : & T ) -> Self {
391
+ b. inc_ref ( ) ;
392
+ // SAFETY: We just incremented the refcount above.
393
+ unsafe { Self :: from_raw ( NonNull :: from ( b) ) }
394
+ }
395
+ }
396
+
397
+ impl < T : AlwaysRefCounted > Drop for ARef < T > {
398
+ fn drop ( & mut self ) {
399
+ // SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to
400
+ // decrement.
401
+ unsafe { T :: dec_ref ( self . ptr ) } ;
402
+ }
403
+ }
404
+
298
405
/// A sum type that always holds either a value of type `L` or `R`.
299
406
pub enum Either < L , R > {
300
407
/// Constructs an instance of [`Either`] containing a value of type `L`.
0 commit comments