<[email protected]> writes: > On Mon, Feb 23, 2026 at 03:59:22PM +0100, Andreas Hindborg wrote: >> Alice Ryhl <[email protected]> writes: >> >> > On Fri, Feb 20, 2026 at 10:51:10AM +0100, Andreas Hindborg wrote: >> >> From: Asahi Lina <[email protected]> >> >> >> >> By analogy to `AlwaysRefCounted` and `ARef`, an `Ownable` type is a >> >> (typically C FFI) type that *may* be owned by Rust, but need not be. >> >> Unlike >> >> `AlwaysRefCounted`, this mechanism expects the reference to be unique >> >> within Rust, and does not allow cloning. >> >> >> >> Conceptually, this is similar to a `KBox<T>`, except that it delegates >> >> resource management to the `T` instead of using a generic allocator. >> >> >> >> [ om: >> >> - Split code into separate file and `pub use` it from types.rs. >> >> - Make from_raw() and into_raw() public. >> >> - Remove OwnableMut, and make DerefMut dependent on Unpin instead. >> >> - Usage example/doctest for Ownable/Owned. >> >> - Fixes to documentation and commit message. >> >> ] >> >> >> >> Link: >> >> https://lore.kernel.org/all/[email protected]/ >> >> Signed-off-by: Asahi Lina <[email protected]> >> >> Co-developed-by: Oliver Mangold <[email protected]> >> >> Signed-off-by: Oliver Mangold <[email protected]> >> >> Reviewed-by: Boqun Feng <[email protected]> >> >> Reviewed-by: Daniel Almeida <[email protected]> >> >> [ Andreas: Updated documentation, examples, and formatting ] >> >> Reviewed-by: Gary Guo <[email protected]> >> >> Co-developed-by: Andreas Hindborg <[email protected]> >> >> Signed-off-by: Andreas Hindborg <[email protected]> >> > >> >> +/// let result = NonNull::new(KBox::into_raw(result)) >> >> +/// .expect("Raw pointer to newly allocation KBox is null, >> >> this should never happen."); >> > >> > KBox should probably have an into_raw_nonnull(). >> >> I can add that. >> >> > >> >> +/// let foo = Foo::new().expect("Failed to allocate a Foo. This >> >> shouldn't happen"); >> >> +/// assert!(*FOO_ALLOC_COUNT.lock() == 1); >> > >> > Use ? here. >> >> Ok. >> >> > >> >> +/// } >> >> +/// // `foo` is out of scope now, so we expect no live allocations. >> >> +/// assert!(*FOO_ALLOC_COUNT.lock() == 0); >> >> +/// ``` >> >> +pub unsafe trait Ownable { >> >> + /// Releases the object. >> >> + /// >> >> + /// # Safety >> >> + /// >> >> + /// Callers must ensure that: >> >> + /// - `this` points to a valid `Self`. >> >> + /// - `*this` is no longer used after this call. >> >> + unsafe fn release(this: NonNull<Self>); >> > >> > Honestly, not using it after this call may be too strong. I can imagine >> > wanting a value where I have both an ARef<_> and Owned<_> reference to >> > something similar to the existing Arc<_>/ListArc<_> pattern, and in that >> > case the value may in fact be accessed after this call if you still have >> > an ARef<_>. >> >> I do not understand your use case. >> >> You are not supposed to have both an `ARef` and an `Owned` at the same >> time. The `Owned` is to `ARef` what `UniqueArc` is to `Arc`. It is >> supposed to be unique and no `ARef` can be live while the `Owned` is >> live. >> >> A `ListArc` is "at most one per list link" and it takes a refcount on >> the object by owning an `Arc`. As far as I recall, it does not provide >> mutable access to anything but the list link. To me, that is a very >> different situation. > > I mean, even Page is kind of an example like that. > > Pages are refcounted, but when you have a higher-order page, the > __free_pages() call does something special beyond what put_page(). For > example, if you have an order-2 page, which consists of 4 pages, then > the refcount only keeps the first page alive, and __free_pages() frees > the 3 extra pages right away even if refcount is still non-zero. The > first page then stays alive until the last put_page() is called.
I see. We currently only support order 0 pages. I think we can handle this situation later, if we need to handle higher order pages. In that case, we could hand out `Owned<Page>` for the head page and then provide some way of getting a `&Page` for the tail pages. Obtaining `Owned<Page>` for a tail page does not make sense. More likely we will build an abstraction for `struct folio`. We can still hand some kind of page reference for tail pages from an `Owned<Folio>`. Best regards, Andreas Hindborg
