From: James Sedgwick Date: Fri, 18 Sep 2015 22:24:53 +0000 (-0700) Subject: move ThreadWheelTimekeeper out of detail X-Git-Tag: deprecate-dynamic-initializer~390 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=77bea361da2080c0a596ac0cc640a37b84091488;p=folly.git move ThreadWheelTimekeeper out of detail Summary: This can be useful on its own, will use in twagent Reviewed By: @fugalh Differential Revision: D2457778 --- diff --git a/folly/Makefile.am b/folly/Makefile.am index 49c22ef6..2d90adde 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -148,13 +148,13 @@ nobase_follyinclude_HEADERS = \ futures/ScheduledExecutor.h \ futures/SharedPromise.h \ futures/SharedPromise-inl.h \ + futures/ThreadWheelTimekeeper.h \ futures/Timekeeper.h \ futures/Try-inl.h \ futures/Try.h \ futures/Unit.h \ futures/detail/Core.h \ futures/detail/FSM.h \ - futures/detail/ThreadWheelTimekeeper.h \ futures/detail/Types.h \ gen/Base.h \ gen/Base-inl.h \ @@ -317,13 +317,13 @@ libfolly_la_SOURCES = \ File.cpp \ FileUtil.cpp \ FingerprintTables.cpp \ - futures/detail/ThreadWheelTimekeeper.cpp \ futures/Barrier.cpp \ futures/ThreadedExecutor.cpp \ futures/Future.cpp \ futures/InlineExecutor.cpp \ futures/ManualExecutor.cpp \ futures/QueuedImmediateExecutor.cpp \ + futures/ThreadWheelTimekeeper.cpp \ detail/Futex.cpp \ GroupVarint.cpp \ GroupVarintTables.cpp \ diff --git a/folly/futures/Future.cpp b/folly/futures/Future.cpp index 501322a1..bbab4003 100644 --- a/folly/futures/Future.cpp +++ b/folly/futures/Future.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ #include -#include +#include #include namespace folly { diff --git a/folly/futures/ThreadWheelTimekeeper.cpp b/folly/futures/ThreadWheelTimekeeper.cpp new file mode 100644 index 00000000..e65f3dbb --- /dev/null +++ b/folly/futures/ThreadWheelTimekeeper.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2015 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. + */ +#include "ThreadWheelTimekeeper.h" + +#include +#include +#include + +namespace folly { + +namespace { + Singleton timekeeperSingleton_; + + // Our Callback object for HHWheelTimer + struct WTCallback : public folly::HHWheelTimer::Callback { + // Only allow creation by this factory, to ensure heap allocation. + static WTCallback* create(EventBase* base) { + // optimization opportunity: memory pool + return new WTCallback(base); + } + + Future getFuture() { + return promise_.getFuture(); + } + + protected: + EventBase* base_; + Promise promise_; + + explicit WTCallback(EventBase* base) + : base_(base) { + promise_.setInterruptHandler( + std::bind(&WTCallback::interruptHandler, this)); + } + + void timeoutExpired() noexcept override { + promise_.setValue(); + delete this; + } + + void interruptHandler() { + base_->runInEventBaseThread([=] { + cancelTimeout(); + delete this; + }); + } + }; + +} // namespace + + +ThreadWheelTimekeeper::ThreadWheelTimekeeper() : + thread_([this]{ eventBase_.loopForever(); }), + wheelTimer_(new HHWheelTimer(&eventBase_, std::chrono::milliseconds(1))) +{ + eventBase_.waitUntilRunning(); + eventBase_.runInEventBaseThread([this]{ + // 15 characters max + eventBase_.setName("FutureTimekeepr"); + }); +} + +ThreadWheelTimekeeper::~ThreadWheelTimekeeper() { + eventBase_.runInEventBaseThreadAndWait([this]{ + wheelTimer_->cancelAll(); + eventBase_.terminateLoopSoon(); + }); + thread_.join(); +} + +Future ThreadWheelTimekeeper::after(Duration dur) { + auto cob = WTCallback::create(&eventBase_); + auto f = cob->getFuture(); + eventBase_.runInEventBaseThread([=]{ + wheelTimer_->scheduleTimeout(cob, dur); + }); + return f; +} + +namespace detail { + +Timekeeper* getTimekeeperSingleton() { + return timekeeperSingleton_.get(); +} + +} // detail + +} // folly diff --git a/folly/futures/ThreadWheelTimekeeper.h b/folly/futures/ThreadWheelTimekeeper.h new file mode 100644 index 00000000..63cb23a2 --- /dev/null +++ b/folly/futures/ThreadWheelTimekeeper.h @@ -0,0 +1,48 @@ +/* + * Copyright 2015 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 +#include +#include +#include +#include + +namespace folly { + +/// The default Timekeeper implementation which uses a HHWheelTimer on an +/// EventBase in a dedicated thread. Users needn't deal with this directly, it +/// is used by default by Future methods that work with timeouts. +class ThreadWheelTimekeeper : public Timekeeper { + public: + /// But it doesn't *have* to be a singleton. + ThreadWheelTimekeeper(); + ~ThreadWheelTimekeeper() override; + + /// Implement the Timekeeper interface + /// This future *does* complete on the timer thread. You should almost + /// certainly follow it with a via() call or the accuracy of other timers + /// will suffer. + Future after(Duration) override; + + protected: + folly::EventBase eventBase_; + std::thread thread_; + HHWheelTimer::UniquePtr wheelTimer_; +}; + +} // folly diff --git a/folly/futures/detail/ThreadWheelTimekeeper.cpp b/folly/futures/detail/ThreadWheelTimekeeper.cpp deleted file mode 100644 index cd10671b..00000000 --- a/folly/futures/detail/ThreadWheelTimekeeper.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2015 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. - */ -#include "ThreadWheelTimekeeper.h" - -#include -#include -#include - -namespace folly { namespace detail { - -namespace { - Singleton timekeeperSingleton_; - - // Our Callback object for HHWheelTimer - struct WTCallback : public folly::HHWheelTimer::Callback { - // Only allow creation by this factory, to ensure heap allocation. - static WTCallback* create(EventBase* base) { - // optimization opportunity: memory pool - return new WTCallback(base); - } - - Future getFuture() { - return promise_.getFuture(); - } - - protected: - EventBase* base_; - Promise promise_; - - explicit WTCallback(EventBase* base) - : base_(base) { - promise_.setInterruptHandler( - std::bind(&WTCallback::interruptHandler, this)); - } - - void timeoutExpired() noexcept override { - promise_.setValue(); - delete this; - } - - void interruptHandler() { - base_->runInEventBaseThread([=] { - cancelTimeout(); - delete this; - }); - } - }; - -} // namespace - - -ThreadWheelTimekeeper::ThreadWheelTimekeeper() : - thread_([this]{ eventBase_.loopForever(); }), - wheelTimer_(new HHWheelTimer(&eventBase_, std::chrono::milliseconds(1))) -{ - eventBase_.waitUntilRunning(); - eventBase_.runInEventBaseThread([this]{ - // 15 characters max - eventBase_.setName("FutureTimekeepr"); - }); -} - -ThreadWheelTimekeeper::~ThreadWheelTimekeeper() { - eventBase_.runInEventBaseThreadAndWait([this]{ - wheelTimer_->cancelAll(); - eventBase_.terminateLoopSoon(); - }); - thread_.join(); -} - -Future ThreadWheelTimekeeper::after(Duration dur) { - auto cob = WTCallback::create(&eventBase_); - auto f = cob->getFuture(); - eventBase_.runInEventBaseThread([=]{ - wheelTimer_->scheduleTimeout(cob, dur); - }); - return f; -} - -Timekeeper* getTimekeeperSingleton() { - return timekeeperSingleton_.get(); -} - -}} // folly::detail diff --git a/folly/futures/detail/ThreadWheelTimekeeper.h b/folly/futures/detail/ThreadWheelTimekeeper.h deleted file mode 100644 index 9625de78..00000000 --- a/folly/futures/detail/ThreadWheelTimekeeper.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2015 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 -#include -#include -#include -#include - -namespace folly { namespace detail { - -/// The default Timekeeper implementation which uses a HHWheelTimer on an -/// EventBase in a dedicated thread. Users needn't deal with this directly, it -/// is used by default by Future methods that work with timeouts. -class ThreadWheelTimekeeper : public Timekeeper { - public: - /// But it doesn't *have* to be a singleton. - ThreadWheelTimekeeper(); - ~ThreadWheelTimekeeper() override; - - /// Implement the Timekeeper interface - /// This future *does* complete on the timer thread. You should almost - /// certainly follow it with a via() call or the accuracy of other timers - /// will suffer. - Future after(Duration) override; - - protected: - folly::EventBase eventBase_; - std::thread thread_; - HHWheelTimer::UniquePtr wheelTimer_; -}; - -Timekeeper* getTimekeeperSingleton(); - -}} // folly::detail