@@ -25,8 +25,8 @@ use core::{
25
25
cell:: UnsafeCell ,
26
26
convert:: { AsRef , TryFrom } ,
27
27
marker:: { PhantomData , Unsize } ,
28
- mem:: ManuallyDrop ,
29
- ops:: Deref ,
28
+ mem:: { ManuallyDrop , MaybeUninit } ,
29
+ ops:: { Deref , DerefMut } ,
30
30
pin:: Pin ,
31
31
ptr:: { self , NonNull } ,
32
32
} ;
@@ -75,17 +75,10 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Ref<T> {}
75
75
impl < T > Ref < T > {
76
76
/// Constructs a new reference counted instance of `T`.
77
77
pub fn try_new ( contents : T ) -> Result < Self > {
78
- Self :: try_new_and_init ( contents, |_| { } )
79
- }
80
-
81
- /// Constructs a new reference counted instance of `T` and calls the initialisation function.
82
- ///
83
- /// This is useful because it provides a mutable reference to `T` at its final location.
84
- pub fn try_new_and_init < U : FnOnce ( Pin < & mut T > ) > ( contents : T , init : U ) -> Result < Self > {
85
78
let layout = Layout :: new :: < RefInner < T > > ( ) ;
86
79
// SAFETY: The layout size is guaranteed to be non-zero because `RefInner` contains the
87
80
// reference count.
88
- let mut inner = NonNull :: new ( unsafe { alloc ( layout) } )
81
+ let inner = NonNull :: new ( unsafe { alloc ( layout) } )
89
82
. ok_or ( Error :: ENOMEM ) ?
90
83
. cast :: < RefInner < T > > ( ) ;
91
84
@@ -98,18 +91,18 @@ impl<T> Ref<T> {
98
91
// SAFETY: `inner` is writable and properly aligned.
99
92
unsafe { inner. as_ptr ( ) . write ( value) } ;
100
93
101
- // SAFETY: By the invariant, `RefInner` is pinned and `T` is also pinned.
102
- let pinned = unsafe { Pin :: new_unchecked ( & mut inner. as_mut ( ) . data ) } ;
103
-
104
- // INVARIANT: The only places where `&mut T` is available are here, which is explicitly
105
- // pinned, and in `drop`. Both are compatible with the pin requirements.
106
- init ( pinned) ;
107
-
108
94
// SAFETY: We just created `inner` with a reference count of 1, which is owned by the new
109
95
// `Ref` object.
110
96
Ok ( unsafe { Self :: from_inner ( inner) } )
111
97
}
112
98
99
+ /// Constructs a new reference counted instance of `T` and calls the initialisation function.
100
+ ///
101
+ /// This is useful because it provides a mutable reference to `T` at its final location.
102
+ pub fn try_new_and_init < U : FnOnce ( Pin < & mut T > ) > ( contents : T , init : U ) -> Result < Self > {
103
+ Ok ( UniqueRef :: try_new ( contents) ?. pin_init_and_share ( init) )
104
+ }
105
+
113
106
/// Deconstructs a [`Ref`] object into a `usize`.
114
107
///
115
108
/// It can be reconstructed once via [`Ref::from_usize`].
@@ -306,6 +299,12 @@ impl<T> TryFrom<Vec<T>> for Ref<[T]> {
306
299
}
307
300
}
308
301
302
+ impl < T : ?Sized > From < UniqueRef < T > > for Ref < T > {
303
+ fn from ( item : UniqueRef < T > ) -> Self {
304
+ item. inner
305
+ }
306
+ }
307
+
309
308
/// A borrowed [`Ref`] with manually-managed lifetime.
310
309
///
311
310
/// # Invariants
@@ -337,3 +336,145 @@ impl<T: ?Sized> Deref for RefBorrow<T> {
337
336
self . inner_ref . deref ( )
338
337
}
339
338
}
339
+
340
+ /// A refcounted object that is known to have a refcount of 1.
341
+ ///
342
+ /// It is mutable and can be converted to a [`Ref`] so that it can be shared.
343
+ ///
344
+ /// # Invariants
345
+ ///
346
+ /// `inner` always has a reference count of 1.
347
+ ///
348
+ /// # Examples
349
+ ///
350
+ /// In the following example, we make changes to the inner object before turning it into a
351
+ /// `Ref<Test>` object (after which point, it cannot be mutated directly). Note that `x.into()`
352
+ /// cannot fail.
353
+ ///
354
+ /// ```
355
+ /// # use kernel::prelude::*;
356
+ /// use kernel::sync::{Ref, UniqueRef};
357
+ ///
358
+ /// struct Example {
359
+ /// a: u32,
360
+ /// b: u32,
361
+ /// }
362
+ ///
363
+ /// fn test() -> Result<Ref<Example>> {
364
+ /// let mut x = UniqueRef::try_new(Example { a: 10, b: 20 })?;
365
+ /// x.a += 1;
366
+ /// x.b += 1;
367
+ /// Ok(x.into())
368
+ /// }
369
+ /// ```
370
+ ///
371
+ /// In the following example we first allocate memory for a ref-counted `Example` but we don't
372
+ /// initialise it on allocation. We do initialise it later with a call to [`UniqueRef::write`],
373
+ /// followed by a conversion to `Ref<Example>`. This is particularly useful when allocation happens
374
+ /// in one context (e.g., sleepable) and initialisation in another (e.g., atomic):
375
+ ///
376
+ /// ```
377
+ /// # use kernel::prelude::*;
378
+ /// use kernel::sync::{Ref, UniqueRef};
379
+ ///
380
+ /// struct Example {
381
+ /// a: u32,
382
+ /// b: u32,
383
+ /// }
384
+ ///
385
+ /// fn test2() -> Result<Ref<Example>> {
386
+ /// let x = UniqueRef::try_new_uninit()?;
387
+ /// Ok(x.write(Example { a: 10, b: 20 }).into())
388
+ /// }
389
+ /// ```
390
+ ///
391
+ /// In the last example below, the caller gets a pinned instance of `Example` while converting to
392
+ /// `Ref<Example>`; this is useful in scenarios where one needs a pinned reference during
393
+ /// initialisation, for example, when initialising fields that are wrapped in locks.
394
+ ///
395
+ /// ```
396
+ /// # use kernel::prelude::*;
397
+ /// use kernel::sync::{Ref, UniqueRef};
398
+ ///
399
+ /// struct Example {
400
+ /// a: u32,
401
+ /// b: u32,
402
+ /// }
403
+ ///
404
+ /// fn test2() -> Result<Ref<Example>> {
405
+ /// let mut x = UniqueRef::try_new(Example { a: 10, b: 20 })?;
406
+ /// // We can modify `pinned` because it is `Unpin`.
407
+ /// Ok(x.pin_init_and_share(|mut pinned| pinned.a += 1))
408
+ /// }
409
+ /// ```
410
+ pub struct UniqueRef < T : ?Sized > {
411
+ inner : Ref < T > ,
412
+ }
413
+
414
+ impl < T > UniqueRef < T > {
415
+ /// Tries to allocate a new [`UniqueRef`] instance.
416
+ pub fn try_new ( value : T ) -> Result < Self > {
417
+ Ok ( Self {
418
+ // INVARIANT: The newly-created object has a ref-count of 1.
419
+ inner : Ref :: try_new ( value) ?,
420
+ } )
421
+ }
422
+
423
+ /// Tries to allocate a new [`UniqueRef`] instance whose contents are not initialised yet.
424
+ pub fn try_new_uninit ( ) -> Result < UniqueRef < MaybeUninit < T > > > {
425
+ Ok ( UniqueRef :: < MaybeUninit < T > > {
426
+ // INVARIANT: The newly-created object has a ref-count of 1.
427
+ inner : Ref :: try_new ( MaybeUninit :: uninit ( ) ) ?,
428
+ } )
429
+ }
430
+ }
431
+
432
+ impl < T : ?Sized > UniqueRef < T > {
433
+ /// Converts a [`UniqueRef<T>`] into a [`Ref<T>`].
434
+ ///
435
+ /// It allows callers to get a `Pin<&mut T>` that they can use to initialise the inner object
436
+ /// just before it becomes shareable.
437
+ pub fn pin_init_and_share < U : FnOnce ( Pin < & mut T > ) > ( mut self , init : U ) -> Ref < T > {
438
+ let inner = self . deref_mut ( ) ;
439
+
440
+ // SAFETY: By the `Ref` invariant, `RefInner` is pinned and `T` is also pinned.
441
+ let pinned = unsafe { Pin :: new_unchecked ( inner) } ;
442
+
443
+ // INVARIANT: The only places where `&mut T` is available are here (where it is explicitly
444
+ // pinned, i.e. implementations of `init` will see a Pin<&mut T>), and in `Ref::drop`. Both
445
+ // are compatible with the pin requirements of the invariants of `Ref`.
446
+ init ( pinned) ;
447
+
448
+ self . into ( )
449
+ }
450
+ }
451
+
452
+ impl < T > UniqueRef < MaybeUninit < T > > {
453
+ /// Converts a `UniqueRef<MaybeUninit<T>>` into a `UniqueRef<T>` by writing a value into it.
454
+ pub fn write ( mut self , value : T ) -> UniqueRef < T > {
455
+ self . deref_mut ( ) . write ( value) ;
456
+ let inner = ManuallyDrop :: new ( self ) . inner . ptr ;
457
+ UniqueRef {
458
+ // SAFETY: The new `Ref` is taking over `ptr` from `self.inner` (which won't be
459
+ // dropped). The types are compatible because `MaybeUninit<T>` is compatible with `T`.
460
+ inner : unsafe { Ref :: from_inner ( inner. cast ( ) ) } ,
461
+ }
462
+ }
463
+ }
464
+
465
+ impl < T : ?Sized > Deref for UniqueRef < T > {
466
+ type Target = T ;
467
+
468
+ fn deref ( & self ) -> & Self :: Target {
469
+ self . inner . deref ( )
470
+ }
471
+ }
472
+
473
+ impl < T : ?Sized > DerefMut for UniqueRef < T > {
474
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
475
+ // SAFETY: By the `Ref` type invariant, there is necessarily a reference to the object, so
476
+ // it is safe to dereference it. Additionally, we know there is only one reference when
477
+ // it's inside a `UniqueRef`, so it is safe to get a mutable reference.
478
+ unsafe { & mut self . inner . ptr . as_mut ( ) . data }
479
+ }
480
+ }
0 commit comments