All of lore.kernel.org
 help / color / mirror / Atom feed
From: Danilo Krummrich <dakr@kernel.org>
To: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Cc: rust-for-linux@vger.kernel.org, aliceryhl@google.com,
	dakr@redhat.com, linux-kernel@vger.kernel.org,
	airlied@redhat.com, miguel.ojeda.sandonis@gmail.com,
	boqun.feng@gmail.com
Subject: Re: [PATCH v2 1/5] rust: types: add `Owned` type and `Ownable` trait
Date: Wed, 23 Oct 2024 10:10:45 +0200	[thread overview]
Message-ID: <ZxivhdAkTl9xXCBs@pollux> (raw)
In-Reply-To: <20241022224832.1505432-2-abdiel.janulgue@gmail.com>

On Wed, Oct 23, 2024 at 01:44:45AM +0300, Abdiel Janulgue wrote:
> Add the 'Owned' type, a simple smart pointer type that owns the
> underlying data.
> 
> An object implementing `Ownable' can constructed by wrapping it in
> `Owned`, which has the advantage of allowing fine-grained control
> over it's resource allocation and deallocation.
> 
> Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
> ---
>  rust/kernel/types.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
> 
> diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
> index ced143600eb1..3f632916bd4d 100644
> --- a/rust/kernel/types.rs
> +++ b/rust/kernel/types.rs
> @@ -429,3 +429,65 @@ pub enum Either<L, R> {
>      /// Constructs an instance of [`Either`] containing a value of type `R`.
>      Right(R),
>  }
> +
> +/// A smart pointer that owns the underlying data `T`.
> +///
> +/// This is a simple smart pointer that owns the underlying data. Typically, this would be
> +/// returned as a wrapper for `T` in `T`'s constructor.
> +/// When an object adds an option of being constructed this way, in addition to implementing
> +/// `Drop`, it implements `Ownable` as well, thus having finer-grained control in where
> +/// resource allocation and deallocation happens.
> +///
> +/// # Invariants
> +///
> +/// The pointer is always valid and owns the underlying data.
> +pub struct Owned<T: Ownable> {
> +    ptr: NonNull<T>,
> +}
> +
> +impl<T: Ownable> Owned<T> {
> +    /// Creates a new smart pointer that owns `T`.
> +    ///
> +    /// # Safety
> +    /// `ptr` needs to be a valid pointer, and it should be the unique owner to the object,
> +    /// in other words, no other entity should free the underlying data.
> +    pub unsafe fn to_owned(ptr: *mut T) -> Self {
> +	// SAFETY: Per function safety requirement.
> +	Self { ptr: unsafe { NonNull::new_unchecked(ptr) } }
> +    }

I wonder if this should just be

   pub fn new(ptr: NonNull<T>) -> Self

This way the caller could decide whether to use the fallible variant
`NonNull::new` or `NonNull::new_unchecked`.

Alternatively, you could have your own `new` and `new_unchecked` methods, but
that seems a bit redundant.

Sometimes this might be more elegant. For instance in the page code, as it is
now, you have to give up on

   let page = NonNull::new(page).ok_or(AllocError)?;

and instead have to do a NULL check by hand for the subsequent unsafe call to
`Owned::to_owned`.

> +}
> +
> +impl<T: Ownable> Deref for Owned<T> {
> +    type Target = T;
> +
> +    fn deref(&self) -> &Self::Target {
> +        // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
> +        // safe to dereference it.
> +        unsafe { self.ptr.as_ref() }
> +    }
> +}
> +
> +impl<T: Ownable> DerefMut for Owned<T> {
> +    fn deref_mut(&mut self) -> &mut Self::Target {
> +        // SAFETY: By the type invariant, there is necessarily a reference to the object, so it is
> +        // safe to dereference it.
> +        unsafe { self.ptr.as_mut() }
> +    }
> +}
> +
> +/// An Ownable type is a type that can be put into `Owned<T>`, and when `Owned<T>` drops,
> +/// `ptr_drop` will be called.
> +pub unsafe trait Ownable {
> +    /// # Safety
> +    /// This could only be called in the `Owned::drop` function.
> +    unsafe fn ptr_drop(ptr: *mut Self);
> +}
> +
> +impl<T: Ownable> Drop for Owned<T> {
> +    fn drop(&mut self) {
> +	// SAFETY: In Owned<T>::drop.
> +	unsafe {
> +	    <T as Ownable>::ptr_drop(self.ptr.as_mut());
> +	}
> +    }
> +}
> -- 
> 2.43.0
> 

  reply	other threads:[~2024-10-23  8:10 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-22 22:44 [PATCH v2 0/5] Introduce Owned type and Ownable trait (was: "rust: page: Add support for vmalloc_to_page") Abdiel Janulgue
2024-10-22 22:44 ` [PATCH v2 1/5] rust: types: add `Owned` type and `Ownable` trait Abdiel Janulgue
2024-10-23  8:10   ` Danilo Krummrich [this message]
2024-10-23  9:28   ` Alice Ryhl
2024-10-23 10:26     ` Abdiel Janulgue
2024-10-23 14:58       ` Boqun Feng
2024-10-23 17:52         ` Alice Ryhl
2024-10-23 18:07           ` Boqun Feng
2024-10-24  7:23             ` Alice Ryhl
2024-10-24  7:33               ` Alice Ryhl
2024-11-01 13:38                 ` Abdiel Janulgue
2024-11-01 13:49                   ` Alice Ryhl
2024-10-22 22:44 ` [PATCH v2 2/5] rust: page: Make ownership of the page pointer explicit Abdiel Janulgue
2024-10-22 22:44 ` [PATCH v2 3/5] rust: page: Extend support to vmalloc_to_page Abdiel Janulgue
2024-10-23  8:42   ` Danilo Krummrich
2024-10-23  9:03     ` Danilo Krummrich
2024-10-23 10:26     ` Abdiel Janulgue
2024-10-23 11:30       ` Danilo Krummrich
2024-10-22 22:44 ` [PATCH v2 4/5] rust: page: Add page_slice_to_page Abdiel Janulgue
2024-10-22 22:44 ` [PATCH v2 5/5] rust: firmware: implement `Ownable` for Firmware Abdiel Janulgue
2024-10-23  9:35   ` Danilo Krummrich
2024-10-23  9:45     ` Danilo Krummrich
2024-10-27 22:20     ` Boqun Feng
2024-10-28 13:37       ` Danilo Krummrich
2024-10-23  8:03 ` [PATCH v2 0/5] Introduce Owned type and Ownable trait (was: "rust: page: Add support for vmalloc_to_page") Danilo Krummrich
2024-10-23  9:51   ` Miguel Ojeda
2024-10-23 12:01     ` Danilo Krummrich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZxivhdAkTl9xXCBs@pollux \
    --to=dakr@kernel.org \
    --cc=abdiel.janulgue@gmail.com \
    --cc=airlied@redhat.com \
    --cc=aliceryhl@google.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miguel.ojeda.sandonis@gmail.com \
    --cc=rust-for-linux@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.