Created
May 30, 2024 20:00
-
-
Save ellcs/cf19804bed1e1c709bc02accd9c1230e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit d15c08793a46e2776b4fbc0d01545a1035d024b2 | |
Author: idc <idc> | |
Date: Tue May 28 14:11:48 2024 -0700 | |
Add associated type for pinnedresult | |
diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs | |
index 424257284..9eb78b7f3 100644 | |
--- a/rust/kernel/init.rs | |
+++ b/rust/kernel/init.rs | |
@@ -202,24 +202,25 @@ | |
//! [stack]: crate::stack_pin_init | |
//! [`Arc<T>`]: crate::sync::Arc | |
//! [`impl PinInit<Foo>`]: PinInit | |
//! [`impl PinInit<T, E>`]: PinInit | |
//! [`impl Init<T, E>`]: Init | |
//! [`Opaque`]: kernel::types::Opaque | |
//! [`Opaque::ffi_init`]: kernel::types::Opaque::ffi_init | |
//! [`pin_data`]: ::macros::pin_data | |
//! [`pin_init!`]: crate::pin_init! | |
use crate::{ | |
error::{self, Error}, | |
+ sync::Arc, | |
sync::UniqueArc, | |
types::{Opaque, ScopeGuard}, | |
}; | |
use alloc::boxed::Box; | |
use core::{ | |
alloc::AllocError, | |
cell::UnsafeCell, | |
convert::Infallible, | |
marker::PhantomData, | |
mem::MaybeUninit, | |
num::*, | |
pin::Pin, | |
@@ -1102,37 +1103,41 @@ unsafe fn __init(self, slot: *mut T) -> Result<(), E> { | |
} | |
} | |
// SAFETY: Every type can be initialized by-value. `__pinned_init` calls `__init`. | |
unsafe impl<T, E> PinInit<T, E> for T { | |
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { | |
unsafe { self.__init(slot) } | |
} | |
} | |
/// Smart pointer that can initialize memory in-place. | |
pub trait InPlaceInit<T>: Sized { | |
+ /// A type might be pinned implicitly. An addtional `Pin<ImplicitlyPinned>` is useless. In | |
+ /// doubt, the type can just be set to `Pin<Self>`. | |
+ type PinnedResult; | |
+ | |
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this | |
/// type. | |
/// | |
/// If `T: !Unpin` it will not be able to move afterwards. | |
- fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E> | |
+ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Self::PinnedResult, E> | |
where | |
E: From<AllocError>; | |
/// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this | |
/// type. | |
/// | |
/// If `T: !Unpin` it will not be able to move afterwards. | |
- fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Pin<Self>> | |
+ fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Self::PinnedResult> | |
where | |
Error: From<E>, | |
{ | |
// SAFETY: We delegate to `init` and only change the error type. | |
let init = unsafe { | |
pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e))) | |
}; | |
Self::try_pin_init(init) | |
} | |
/// Use the given initializer to in-place initialize a `T`. | |
fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E> | |
@@ -1143,27 +1148,55 @@ fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E> | |
fn init<E>(init: impl Init<T, E>) -> error::Result<Self> | |
where | |
Error: From<E>, | |
{ | |
// SAFETY: We delegate to `init` and only change the error type. | |
let init = unsafe { | |
init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e))) | |
}; | |
Self::try_init(init) | |
} | |
} | |
+// ``` | |
+// # use kernel::sync::{new_mutex, Arc, Mutex}; | |
+// let mtx: Result<Arc<Mutex<usize>>> = Arc::pin_init(new_mutex!(42, "example::mtx")); | |
+// ``` | |
+impl<T> InPlaceInit<T> for Arc<T> { | |
+ type PinnedResult = Self; | |
+ | |
+ #[inline] | |
+ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Self::PinnedResult, E> | |
+ where | |
+ E: From<AllocError>, | |
+ { | |
+ UniqueArc::try_pin_init(init).map(|u| u.into()) | |
+ } | |
+ | |
+ | |
+ #[inline] | |
+ fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E> | |
+ where | |
+ E: From<AllocError>, | |
+ { | |
+ //kernel::sync::Arc::init(init).map_err(|e| e.into()) | |
+ UniqueArc::try_init(init).map(|u| u.into()) | |
+ } | |
+} | |
+ | |
impl<T> InPlaceInit<T> for Box<T> { | |
+ type PinnedResult = Pin<Self>; | |
+ | |
#[inline] | |
- fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E> | |
+ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Self::PinnedResult, E> | |
where | |
E: From<AllocError>, | |
{ | |
let mut this = Box::try_new_uninit()?; | |
let slot = this.as_mut_ptr(); | |
// SAFETY: When init errors/panics, slot will get deallocated but not dropped, | |
// slot is valid and will not be moved, because we pin it later. | |
unsafe { init.__pinned_init(slot)? }; | |
// SAFETY: All fields have been initialized. | |
Ok(unsafe { this.assume_init() }.into()) | |
} | |
@@ -1174,26 +1207,28 @@ fn try_init<E>(init: impl Init<T, E>) -> Result<Self, E> | |
{ | |
let mut this = Box::try_new_uninit()?; | |
let slot = this.as_mut_ptr(); | |
// SAFETY: When init errors/panics, slot will get deallocated but not dropped, | |
// slot is valid. | |
unsafe { init.__init(slot)? }; | |
// SAFETY: All fields have been initialized. | |
Ok(unsafe { this.assume_init() }) | |
} | |
} | |
impl<T> InPlaceInit<T> for UniqueArc<T> { | |
+ type PinnedResult = Pin<Self>; | |
+ | |
#[inline] | |
- fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Pin<Self>, E> | |
+ fn try_pin_init<E>(init: impl PinInit<T, E>) -> Result<Self::PinnedResult, E> | |
where | |
E: From<AllocError>, | |
{ | |
let mut this = UniqueArc::try_new_uninit()?; | |
let slot = this.as_mut_ptr(); | |
// SAFETY: When init errors/panics, slot will get deallocated but not dropped, | |
// slot is valid and will not be moved, because we pin it later. | |
unsafe { init.__pinned_init(slot)? }; | |
// SAFETY: All fields have been initialized. | |
Ok(unsafe { this.assume_init() }.into()) | |
} | |
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs | |
index 7d4c4bf58..fd0e87115 100644 | |
--- a/rust/kernel/sync/arc.rs | |
+++ b/rust/kernel/sync/arc.rs | |
@@ -3,30 +3,30 @@ | |
//! A reference-counted pointer. | |
//! | |
//! This module implements a way for users to create reference-counted objects and pointers to | |
//! them. Such a pointer automatically increments and decrements the count, and drops the | |
//! underlying object when it reaches zero. It is also safe to use concurrently from multiple | |
//! threads. | |
//! | |
//! It is different from the standard library's [`Arc`] in a few ways: | |
//! 1. It is backed by the kernel's `refcount_t` type. | |
//! 2. It does not support weak references, which allows it to be half the size. | |
//! 3. It saturates the reference count instead of aborting when it goes over a threshold. | |
//! 4. It does not provide a `get_mut` method, so the ref counted object is pinned. | |
+//! 5. The object in [`Arc`] is pinned implicitly. | |
//! | |
//! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html | |
use crate::{ | |
bindings, | |
- error::{self, Error}, | |
init::{self, InPlaceInit, Init, PinInit}, | |
try_init, | |
types::{ForeignOwnable, Opaque}, | |
}; | |
use alloc::boxed::Box; | |
use core::{ | |
alloc::{AllocError, Layout}, | |
fmt, | |
marker::{PhantomData, Unsize}, | |
mem::{ManuallyDrop, MaybeUninit}, | |
ops::{Deref, DerefMut}, | |
pin::Pin, | |
@@ -168,45 +168,45 @@ pub fn try_new(contents: T) -> Result<Self, AllocError> { | |
// SAFETY: There are no safety requirements for this FFI call. | |
refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }), | |
data: contents, | |
}; | |
let inner = Box::try_new(value)?; | |
// SAFETY: We just created `inner` with a reference count of 1, which is owned by the new | |
// `Arc` object. | |
Ok(unsafe { Self::from_inner(Box::leak(inner).into()) }) | |
} | |
- /// Use the given initializer to in-place initialize a `T`. | |
- /// | |
- /// If `T: !Unpin` it will not be able to move afterwards. | |
- #[inline] | |
- pub fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Self> | |
- where | |
- Error: From<E>, | |
- { | |
- UniqueArc::pin_init(init).map(|u| u.into()) | |
- } | |
- | |
- /// Use the given initializer to in-place initialize a `T`. | |
- /// | |
- /// This is equivalent to [`Arc<T>::pin_init`], since an [`Arc`] is always pinned. | |
- #[inline] | |
- pub fn init<E>(init: impl Init<T, E>) -> error::Result<Self> | |
- where | |
- Error: From<E>, | |
- { | |
- UniqueArc::init(init).map(|u| u.into()) | |
- } | |
+ ///// Use the given initializer to in-place initialize a `T`. | |
+ ///// | |
+ ///// If `T: !Unpin` it will not be able to move afterwards. | |
+ //#[inline] | |
+ //pub fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Self> | |
+ //where | |
+ // Error: From<E>, | |
+ //{ | |
+ // UniqueArc::pin_init(init).map(|u| u.into()) | |
+ //} | |
+ | |
+ ///// Use the given initializer to in-place initialize a `T`. | |
+ ///// | |
+ ///// This is equivalent to [`Arc<T>::pin_init`], since an [`Arc`] is always pinned. | |
+ //#[inline] | |
+ //pub fn init<E>(init: impl Init<T, E>) -> error::Result<Self> | |
+ //where | |
+ // Error: From<E>, | |
+ //{ | |
+ // UniqueArc::init(init).map(|u| u.into()) | |
+ //} | |
} | |
impl<T: ?Sized> Arc<T> { | |
/// Constructs a new [`Arc`] from an existing [`ArcInner`]. | |
/// | |
/// # Safety | |
/// | |
/// The caller must ensure that `inner` points to a valid location and has a non-zero reference | |
/// count, one of which will be owned by the new [`Arc`] instance. | |
unsafe fn from_inner(inner: NonNull<ArcInner<T>>) -> Self { | |
// INVARIANT: By the safety requirements, the invariants hold. | |
Arc { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment