currently, std::sync::OnceLock
makes it pretty easy to accidentally create TOC-TOU errors when trying to use OnceLock
to make code that is only run once. take the following pattern:
if ONCE.get().is_some() { return }
unsafe { /* modify some os-specific state */ }
let _ = ONCE.set(some_os_handle);
if this code is run twice in parallel, it may end up corrupting the OS state. the "proper" way of fixing this is with get_or_init
, but there's a lot of problems with this:
- the signature will make a lot of people only think to use it if they actually need the result for something
- a lot of low-level programmers will avoid using callbacks whenever possible, due to perceiving them as inefficient. (even though it should get inlined in this case, bypassing the overhead).
- callbacks have several limitations, namely their inability to return from their containing function (unlike blocks), so many rust programmers may avoid them for that reason.
if we had write-only references, this could be avoided.
interestingly, this would require a type of write-only reference that must be written to before it is dropped, although this is also desirable to allow them to point to data that implements Drop (so they can be dropped when the reference is taken), and to allow taking write-only references to uninitialized variables.
alternativly, there could be a OnceLockWriteGuard or something similar, although this would need a similar restriction of being unable to be dropped without being written (the write
method would have a self
receiver instead of &self
)