X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fsynchronization%2FCallOnce.h;h=4d4bf0f4b80a812f460a05428bfcd027903ea68e;hp=da938beb069a07864dd28f86ab620ae3cd5eeec4;hb=b529367b595dd4da7e70569cbea36d30ace4fa39;hpb=98c488e23b44105d0e1a5b1d5cd7dea10b5843d5 diff --git a/folly/synchronization/CallOnce.h b/folly/synchronization/CallOnce.h index da938beb..4d4bf0f4 100644 --- a/folly/synchronization/CallOnce.h +++ b/folly/synchronization/CallOnce.h @@ -39,28 +39,32 @@ #include namespace folly { +namespace detail { +template +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 +void FOLLY_NOINLINE call_once_impl_no_inline( + detail::once_flag& flag, + Callable&& f, + Args&&... args) { + std::lock_guard lg(flag.mutex_); + if (flag.called_) { + return; + } - template - friend void call_once(once_flag& flag, Callable&& f, Args&&... args); - template - friend void call_once_impl_no_inline(once_flag& flag, - Callable&& f, - Args&&... args); + std::forward(f)(std::forward(args)...); - private: - std::atomic called_{false}; - folly::SharedMutex mutex_; -}; + flag.called_.store(true, std::memory_order_release); +} +} // namespace detail -template +using once_flag = detail::once_flag; + +template void FOLLY_ALWAYS_INLINE -call_once(once_flag& flag, Callable&& f, Args&&... args) { +call_once(detail::once_flag& flag, Callable&& f, Args&&... args) { if (LIKELY(flag.called_.load(std::memory_order_acquire))) { return; } @@ -68,17 +72,30 @@ call_once(once_flag& flag, Callable&& f, Args&&... args) { flag, std::forward(f), std::forward(args)...); } -// Implementation detail: out-of-line slow path -template -void FOLLY_NOINLINE -call_once_impl_no_inline(once_flag& flag, Callable&& f, Args&&... args) { - std::lock_guard lg(flag.mutex_); - if (flag.called_) { - return; - } +namespace detail { - std::forward(f)(std::forward(args)...); +template +class once_flag { + public: + constexpr once_flag() noexcept = default; + once_flag(const once_flag&) = delete; + once_flag& operator=(const once_flag&) = delete; + + template + friend void ::folly::call_once( + once_flag& flag, + Callable&& f, + Args&&... args); + template + friend void call_once_impl_no_inline( + once_flag& flag, + Callable&& f, + Args&&... args); + + private: + std::atomic called_{false}; + Mutex mutex_; +}; +} // namespace detail - flag.called_.store(true, std::memory_order_release); -} } // namespace folly