#include <folly/SharedMutex.h>
namespace folly {
+namespace detail {
+template <typename Mutex>
+class once_flag;
-class once_flag {
- public:
- constexpr once_flag() noexcept = default;
- once_flag(const once_flag&) = delete;
- once_flag& operator=(const once_flag&) = delete;
+// Implementation detail: out-of-line slow path
+template <class Mutex, class Callable, class... Args>
+void FOLLY_NOINLINE call_once_impl_no_inline(
+ detail::once_flag<Mutex>& flag,
+ Callable&& f,
+ Args&&... args) {
+ std::lock_guard<Mutex> lg(flag.mutex_);
+ if (flag.called_) {
+ return;
+ }
- template <typename Callable, class... Args>
- friend void call_once(once_flag& flag, Callable&& f, Args&&... args);
- template <typename Callable, class... Args>
- friend void call_once_impl_no_inline(once_flag& flag,
- Callable&& f,
- Args&&... args);
+ std::forward<Callable>(f)(std::forward<Args>(args)...);
- private:
- std::atomic<bool> called_{false};
- folly::SharedMutex mutex_;
-};
+ flag.called_.store(true, std::memory_order_release);
+}
+} // namespace detail
-template <class Callable, class... Args>
+using once_flag = detail::once_flag<folly::SharedMutex>;
+
+template <class Mutex, class Callable, class... Args>
void FOLLY_ALWAYS_INLINE
-call_once(once_flag& flag, Callable&& f, Args&&... args) {
+call_once(detail::once_flag<Mutex>& flag, Callable&& f, Args&&... args) {
if (LIKELY(flag.called_.load(std::memory_order_acquire))) {
return;
}
flag, std::forward<Callable>(f), std::forward<Args>(args)...);
}
-// Implementation detail: out-of-line slow path
-template <class Callable, class... Args>
-void FOLLY_NOINLINE
-call_once_impl_no_inline(once_flag& flag, Callable&& f, Args&&... args) {
- std::lock_guard<folly::SharedMutex> lg(flag.mutex_);
- if (flag.called_) {
- return;
- }
+namespace detail {
- std::forward<Callable>(f)(std::forward<Args>(args)...);
+template <typename Mutex>
+class once_flag {
+ public:
+ constexpr once_flag() noexcept = default;
+ once_flag(const once_flag&) = delete;
+ once_flag& operator=(const once_flag&) = delete;
+
+ template <typename Mutex_, typename Callable, class... Args>
+ friend void ::folly::call_once(
+ once_flag<Mutex_>& flag,
+ Callable&& f,
+ Args&&... args);
+ template <typename Mutex_, typename Callable, class... Args>
+ friend void call_once_impl_no_inline(
+ once_flag<Mutex_>& flag,
+ Callable&& f,
+ Args&&... args);
+
+ private:
+ std::atomic<bool> called_{false};
+ Mutex mutex_;
+};
+} // namespace detail
- flag.called_.store(true, std::memory_order_release);
-}
} // namespace folly