ladybird/Libraries/LibSync/Once.h

37 lines
879 B
C
Raw Permalink Normal View History

/*
* Copyright (c) 2025, Ryszard Goc <ryszardgoc@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Atomic.h>
#include <AK/Concepts.h>
#include <LibSync/Mutex.h>
namespace Sync {
struct OnceFlag {
Sync::Mutex mutex;
Atomic<bool> has_been_called { false };
};
template<VoidFunction Callable>
void call_once(OnceFlag& flag, Callable&& callable)
{
if (!flag.has_been_called.load(MemoryOrder::memory_order_acquire)) {
Sync::MutexLocker lock(flag.mutex);
// Another thread may have called the function while we were waiting on the mutex
// The mutex guarantees exclusivity so we can use relaxed ordering
if (flag.has_been_called.load(MemoryOrder::memory_order_relaxed))
return;
callable();
flag.has_been_called.store(true, MemoryOrder::memory_order_release);
}
}
}