diff --git a/folly/SingletonThreadLocal.h b/folly/SingletonThreadLocal.h index 01e5a654334..71304411929 100644 --- a/folly/SingletonThreadLocal.h +++ b/folly/SingletonThreadLocal.h @@ -212,9 +212,12 @@ class SingletonThreadLocal { } }; +FOLLY_PUSH_WARNING +FOLLY_CLANG_DISABLE_WARNING("-Wglobal-constructors") template detail::UniqueInstance SingletonThreadLocal::unique{ tag, tag, tag}; +FOLLY_POP_WARNING } // namespace folly diff --git a/folly/executors/SerialExecutor.cpp b/folly/executors/SerialExecutor-inl.h similarity index 63% rename from folly/executors/SerialExecutor.cpp rename to folly/executors/SerialExecutor-inl.h index aae26bc23d2..699075cb979 100644 --- a/folly/executors/SerialExecutor.cpp +++ b/folly/executors/SerialExecutor-inl.h @@ -14,40 +14,48 @@ * limitations under the License. */ -#include - #include #include namespace folly { -SerialExecutor::SerialExecutor(KeepAlive parent) +template +SerialExecutorExt::SerialExecutorExt( + KeepAlive parent) : parent_(std::move(parent)) {} -SerialExecutor::~SerialExecutor() { +template +SerialExecutorExt::~SerialExecutorExt() { DCHECK(!keepAliveCounter_); } -Executor::KeepAlive SerialExecutor::create( - KeepAlive parent) { - return makeKeepAlive(new SerialExecutor(std::move(parent))); +template +Executor::KeepAlive> +SerialExecutorExt::create(KeepAlive parent) { + return makeKeepAlive>( + new SerialExecutorExt(std::move(parent))); } -SerialExecutor::UniquePtr SerialExecutor::createUnique( +template +typename SerialExecutorExt::UniquePtr +SerialExecutorExt::createUnique( std::shared_ptr parent) { - auto executor = new SerialExecutor(getKeepAliveToken(parent.get())); + auto executor = new SerialExecutorExt( + getKeepAliveToken(parent.get())); return {executor, Deleter{std::move(parent)}}; } -bool SerialExecutor::keepAliveAcquire() noexcept { +template +bool SerialExecutorExt::keepAliveAcquire() noexcept { auto keepAliveCounter = keepAliveCounter_.fetch_add(1, std::memory_order_relaxed); DCHECK(keepAliveCounter > 0); return true; } -void SerialExecutor::keepAliveRelease() noexcept { +template +void SerialExecutorExt::keepAliveRelease() noexcept { auto keepAliveCounter = keepAliveCounter_.fetch_sub(1, std::memory_order_acq_rel); DCHECK(keepAliveCounter > 0); @@ -56,14 +64,17 @@ void SerialExecutor::keepAliveRelease() noexcept { } } -void SerialExecutor::add(Func func) { +template +void SerialExecutorExt::add(Func func) { if (scheduleTask(std::move(func))) { parent_->add( [keepAlive = getKeepAliveToken(this)] { keepAlive->worker(); }); } } -void SerialExecutor::addWithPriority(Func func, int8_t priority) { +template +void SerialExecutorExt::addWithPriority( + Func func, int8_t priority) { if (scheduleTask(std::move(func))) { parent_->addWithPriority( [keepAlive = getKeepAliveToken(this)] { keepAlive->worker(); }, @@ -71,14 +82,16 @@ void SerialExecutor::addWithPriority(Func func, int8_t priority) { } } -bool SerialExecutor::scheduleTask(Func&& func) { +template +bool SerialExecutorExt::scheduleTask(Func&& func) { queue_.enqueue(Task{std::move(func), RequestContext::saveContext()}); // If this thread is the first to mark the queue as non-empty, schedule the // worker. return scheduled_.fetch_add(1, std::memory_order_acq_rel) == 0; } -void SerialExecutor::worker() { +template +void SerialExecutorExt::worker() { std::size_t queueSize = scheduled_.load(std::memory_order_acquire); DCHECK_NE(queueSize, 0); diff --git a/folly/executors/SerialExecutor.h b/folly/executors/SerialExecutor.h index d985c1719f4..0bb9c694b9a 100644 --- a/folly/executors/SerialExecutor.h +++ b/folly/executors/SerialExecutor.h @@ -50,31 +50,34 @@ namespace folly { * parent executor is executing tasks. */ -class SerialExecutor : public SerializedExecutor { +template +class SerialExecutorExt : public SerializedExecutor { public: - SerialExecutor(SerialExecutor const&) = delete; - SerialExecutor& operator=(SerialExecutor const&) = delete; - SerialExecutor(SerialExecutor&&) = delete; - SerialExecutor& operator=(SerialExecutor&&) = delete; + SerialExecutorExt(SerialExecutorExt const&) = delete; + SerialExecutorExt& operator=(SerialExecutorExt const&) = delete; + SerialExecutorExt(SerialExecutorExt&&) = delete; + SerialExecutorExt& operator=(SerialExecutorExt&&) = delete; - static KeepAlive create( + static KeepAlive create( KeepAlive parent = getGlobalCPUExecutor()); class Deleter { public: Deleter() {} - void operator()(SerialExecutor* executor) { executor->keepAliveRelease(); } + void operator()(SerialExecutorExt* executor) { + executor->keepAliveRelease(); + } private: - friend class SerialExecutor; + friend class SerialExecutorExt; explicit Deleter(std::shared_ptr parent) : parent_(std::move(parent)) {} std::shared_ptr parent_; }; - using UniquePtr = std::unique_ptr; + using UniquePtr = std::unique_ptr; [[deprecated("Replaced by create")]] static UniquePtr createUnique( std::shared_ptr parent); @@ -104,8 +107,8 @@ class SerialExecutor : public SerializedExecutor { std::shared_ptr ctx; }; - explicit SerialExecutor(KeepAlive parent); - ~SerialExecutor() override; + explicit SerialExecutorExt(KeepAlive parent); + ~SerialExecutorExt() override; bool keepAliveAcquire() noexcept override; @@ -118,9 +121,13 @@ class SerialExecutor : public SerializedExecutor { std::atomic scheduled_{0}; // The consumer should only dequeue when the queue is non-empty, so we don't // need blocking. - folly::UMPSCQueue queue_; + folly::UMPSCQueue queue_; std::atomic keepAliveCounter_{1}; }; +using SerialExecutor = SerialExecutorExt<>; + } // namespace folly + +#include