--- /dev/null
+/*
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+#include "folly/fibers/TimedMutex.h"
+#include "folly/synchronization/CallOnce.h"
+
+namespace folly {
+namespace fibers {
+
+using once_flag = ::folly::detail::once_flag<folly::fibers::TimedMutex>;
+}
+} // namespace folly
#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