Re: [PATCH v1 1/2] rust: Add support for calling a function exactly once

FUJITA Tomonori
2025-11-11T21:44:04Z

On Mon, 10 Nov 2025 21:17:08 -0800
Boqun Feng <boqun.feng@gmail.com> wrote:

> On Tue, Nov 11, 2025 at 12:09:49PM +0900, FUJITA Tomonori wrote:
>> On Mon, 10 Nov 2025 08:14:56 -0800
>> Boqun Feng <boqun.feng@gmail.com> wrote:
>>
>> > On Mon, Nov 10, 2025 at 06:21:50PM +0900, FUJITA Tomonori wrote:
>> >> On Fri, 7 Nov 2025 09:03:01 +0000
>> >> Alice Ryhl <aliceryhl@google.com> wrote:
>> >>
>> >> >> That's my point (and probably also Andreas' point), we already has the
>> >> >> type `SetOnce` to do this, no need for a `OnceLite` type if not
>> >> >> necessary, and the fact that it can be zero'd by debugfs doesn't change
>> >> >> it as I explained above.
>> >> >
>> >> > The SetOnce type doesn't do the same thing as OnceLite. SetOnce has
>> >> > three different states, but OnceLite only needs two. I don't think we
>> >> > should be reusing SetOnce here.
>> >
>> > I mean 3 states should cover 2 states, right? In this case we only need
>> > to support SetOnce<()>, so I think it's fine, see below:
>>
>> Yeah, that would remove access to the value member, but I think that
>> init member could still be accessed in an unintended way.
>>
>
> What an unintended way you mean? Do you have an example?

From my understanding, the init member of SetOnce is designed to be
accessed by using atomic operations, only through its methods. If we
use SetOnce for OnceLite, however, the init member would be written
using non-atomic operations, which is what I referred to as the
"unintended way" since I don't believe Andreas intended it to be
modified in that manner; i.e., not through its methods or by
non-atomic operations.

As I wrote before, in this particular case, I think that it would
still work even if both atomic and non-atomic operations access the
same variable though.

>> >> Yes, SetOnce provides three different states and the feature to set a
>> >> value, which are not necessary for this case.
>> >>
>> >> So there are two design options: 1) to add a new minimal
>> >> implementation that provides only the features required for this case,
>> >
>> > Just to be clear 1) will still need to be in kernel::sync module, as per
>> > our previous discussion.
>>
>> As I wrote before, I think that once_lite.rs could be put in
>> kernel::sync but I'm not sure it's a good idea because I'm not sure if
>> there are any other users who actually need this feature.
>>
>
> Rust std has its own Once[1] module, so I think the concept of "doing
> something once" is going to be more general in Rust code.

That was one of the points of discussion a few months ago,
implementing an equivalent of std's Once for OnceLite would be
over-engineering.

To clarify the behavior, it might be better for OnceLite to be
implemented without atomic operations, similar to the C version?
Unlike Once, as the name suggests, OnceLite is a best-effort mechanism
that only tries to run once.

>> discussion, but I wonder if there are use cases that require Sync. If
>> all access goes through its methods, it seems safe to add Sync.
>>
>>
>> I personally prefer the OnceLite implementation of not using SetOnce,
>> however since it's not directly used by users and can be easily
>> changed later, so I'm fine with any implementation as long as we can
>> reach an agreement soon.
>>
>
> We should always try to find a unified solution, if there is not much
> trouble. Otherwise, we will end up having MyOnce, YourOnce, HisOnce,
> HerOnce, TheirOnce etc in our code base.

I agree that we should always try to use a unified solution whatever
feasible. That said, implementing OnceLite would require modifications
to SetOnce, and I'm concerned that such modifications would just make
SetOnce complicated, which serves no purpose for other use cases.