From: Alice Ryhl <aliceryhl@google.com>
To: Lyude Paul <lyude@redhat.com>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
rust-for-linux@vger.kernel.org, Gary Guo <gary@garyguo.net>,
Ingo Molnar <mingo@redhat.com>, Miguel Ojeda <ojeda@kernel.org>,
Tamir Duberstein <tamird@kernel.org>,
Boqun Feng <boqun@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Viresh Kumar <viresh.kumar@linaro.org>,
Benno Lossin <lossin@kernel.org>, Will Deacon <will@kernel.org>
Subject: Re: [PATCH v2 2/2] rust: sync: Introduce LazyInit
Date: Mon, 1 Jun 2026 08:27:22 +0000 [thread overview]
Message-ID: <ah1CarNtFhCvAAav@google.com> (raw)
In-Reply-To: <20260529173137.303717-3-lyude@redhat.com>
On Fri, May 29, 2026 at 01:30:42PM -0400, Lyude Paul wrote:
> SetOnce is nice, but it does have one problem - you can't use it with
> fallible initializers. While we will be adding support for doing that with
> SetOnce, this leads into another problem: There's no way for racing callers
> to actually block on the initialization of SetOnce, which makes it a
> difficult type to use safely for situations where we want to initialize
> data fallibly once, and then provide access to it to multiple users at once
> until drop.
>
> So to solve this, introduce a new type: LazyInit. LazyInit is like SetOnce
> with a couple of important differences:
>
> * It can't be used in const context
> * It can handle in-place fallible initializers.
> * It uses a Mutex for synchronization instead of an atomic, allowing
> callers to block on initialization.
> * It requires its contents already be Send + Sync, since the Mutex protects
> initializing data and not the data itself.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> + /// Retrieve the contents of `inner.data` and extend their lifetime.
> + ///
> + /// # Safety
> + ///
> + /// The caller guarantees that `self.inner.data` has been previously initialized.
> + #[inline(always)]
> + unsafe fn data<'a>(&'a self, inner: &MutexGuard<'_, Inner<T>>) -> &'a T {
> + // SAFETY:
> + // - Our safety contract guarantees `inner.data` is initialized.
> + // - `T` is `Send` + `Sync`, and thus does not need the `Mutex` for synchronization, making
> + // it safe to hold onto outside of the lock.
> + // - We're guaranteed via `Inner`'s type invariants that so long as immutable references to
> + // self exist, `data` cannot be uninitialized - ensuring it lives throughout the lifetime
> + // of A.
> + // - We're guaranteed the container of `T` will not be written to via `Inner`s type
> + // invariants until `Drop`, ensuring it remains populated for the lifetime of 'a.
> + unsafe { mem::transmute::<&_, &'a _>(inner.data.assume_init_ref()) }
I'm not a big fan of using these kinds of tricks to access the contents
of a mutex after unlocking it. Could we instead use a struct like this:
struct LazyInit<T> {
data: UnsafeCell<MaybeUninit<T>>,
set: AtomicBool,
lock: Mutex<()>,
}
or even:
struct LazyInit<T> {
data: SetOnce<T>,
lock: Mutex<()>,
}
I think this logic will be simpler for everyone.
By the way, another option is to use a similar strategy to
https://lore.kernel.org/rust-for-linux/20260523-upgrade-poll-v4-2-f5b4c747eac2@google.com/
where you just use SetOnce and protect calls to `populate` by another
mutex in the structure. Then you don't need a separate LazyInit.
Alice
next prev parent reply other threads:[~2026-06-01 8:27 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-29 17:30 [PATCH v2 0/2] rust: sync: Introduce LazyInit Lyude Paul
2026-05-29 17:30 ` [PATCH v2 1/2] rust: sync: lock: Add Lock::get_mut_pinned() Lyude Paul
2026-06-01 8:28 ` Alice Ryhl
2026-05-29 17:30 ` [PATCH v2 2/2] rust: sync: Introduce LazyInit Lyude Paul
2026-06-01 8:27 ` Alice Ryhl [this message]
2026-06-01 22:26 ` lyude
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=ah1CarNtFhCvAAav@google.com \
--to=aliceryhl@google.com \
--cc=boqun@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tamird@kernel.org \
--cc=viresh.kumar@linaro.org \
--cc=will@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.