Commit 5c4e6238 authored by Lee Howes's avatar Lee Howes Committed by Facebook GitHub Bot

Current thread executor

Summary: A thread-local query for the current executor. Grounding feature for logging operations.

Reviewed By: andriigrynenko

Differential Revision: D20070133

fbshipit-source-id: e320d2a3d97744b91c07a6060708e5cefc517cb7
parent 8a3363fa
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
#include <folly/Executor.h> #include <folly/Executor.h>
#include <folly/SingletonThreadLocal.h>
#include <stdexcept> #include <stdexcept>
...@@ -35,4 +36,36 @@ void Executor::keepAliveRelease() { ...@@ -35,4 +36,36 @@ void Executor::keepAliveRelease() {
LOG(FATAL) << __func__ << "() should not be called for folly::Executor types " LOG(FATAL) << __func__ << "() should not be called for folly::Executor types "
<< "which do not override keepAliveAcquire()"; << "which do not override keepAliveAcquire()";
} }
namespace {
using BlockingContextSingletonT =
SingletonThreadLocal<folly::Optional<BlockingContext>>;
} // namespace
folly::Optional<BlockingContext> getBlockingContext() {
return BlockingContextSingletonT::get();
}
BlockingGuard::BlockingGuard(folly::StringPiece executorName)
: previousContext_{BlockingContextSingletonT::get()} {
BlockingContextSingletonT::get() = BlockingContext{executorName};
}
BlockingGuard::BlockingGuard()
: previousContext_{BlockingContextSingletonT::get()} {
BlockingContextSingletonT::get() = folly::none;
}
BlockingGuard::~BlockingGuard() {
BlockingContextSingletonT::get() = std::move(previousContext_);
}
BlockingGuard makeBlockingDisallowedGuard(folly::StringPiece executorName) {
return BlockingGuard{executorName};
}
BlockingGuard makeBlockingAllowedGuard() {
return BlockingGuard{};
}
} // namespace folly } // namespace folly
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <utility> #include <utility>
#include <folly/Function.h> #include <folly/Function.h>
#include <folly/Optional.h>
#include <folly/Range.h>
#include <folly/Utility.h> #include <folly/Utility.h>
namespace folly { namespace folly {
...@@ -297,4 +299,32 @@ Executor::KeepAlive<ExecutorT> getKeepAliveToken( ...@@ -297,4 +299,32 @@ Executor::KeepAlive<ExecutorT> getKeepAliveToken(
return ka.copy(); return ka.copy();
} }
struct BlockingContext {
folly::StringPiece executorName;
};
class BlockingGuard;
BlockingGuard makeBlockingDisallowedGuard(folly::StringPiece executorName);
BlockingGuard makeBlockingAllowedGuard();
class [[nodiscard]] BlockingGuard {
public:
~BlockingGuard();
private:
// Disallow blocking
BlockingGuard(folly::StringPiece executorName);
// Empty guard treated as temporarily allowing blocking
BlockingGuard();
friend BlockingGuard makeBlockingDisallowedGuard(
folly::StringPiece executorName);
friend BlockingGuard makeBlockingAllowedGuard();
folly::Optional<BlockingContext> previousContext_;
};
folly::Optional<BlockingContext> getBlockingContext();
} // namespace folly } // namespace folly
...@@ -37,6 +37,8 @@ namespace { ...@@ -37,6 +37,8 @@ namespace {
using default_queue = UnboundedBlockingQueue<CPUThreadPoolExecutor::CPUTask>; using default_queue = UnboundedBlockingQueue<CPUThreadPoolExecutor::CPUTask>;
using default_queue_alloc = using default_queue_alloc =
AlignedSysAllocator<default_queue, FixedAlign<alignof(default_queue)>>; AlignedSysAllocator<default_queue, FixedAlign<alignof(default_queue)>>;
constexpr folly::StringPiece executorName = "CPUThreadPoolExecutor";
} // namespace } // namespace
const size_t CPUThreadPoolExecutor::kDefaultMaxQueueSize = 1 << 14; const size_t CPUThreadPoolExecutor::kDefaultMaxQueueSize = 1 << 14;
...@@ -194,10 +196,12 @@ bool CPUThreadPoolExecutor::taskShouldStop(folly::Optional<CPUTask>& task) { ...@@ -194,10 +196,12 @@ bool CPUThreadPoolExecutor::taskShouldStop(folly::Optional<CPUTask>& task) {
void CPUThreadPoolExecutor::threadRun(ThreadPtr thread) { void CPUThreadPoolExecutor::threadRun(ThreadPtr thread) {
this->threadPoolHook_.registerThread(); this->threadPoolHook_.registerThread();
auto guard = folly::makeBlockingDisallowedGuard(executorName);
thread->startupBaton.post(); thread->startupBaton.post();
while (true) { while (true) {
auto task = taskQueue_->try_take_for(threadTimeout_); auto task = taskQueue_->try_take_for(threadTimeout_);
// Handle thread stopping, either by task timeout, or // Handle thread stopping, either by task timeout, or
// by 'poison' task added in join() or stop(). // by 'poison' task added in join() or stop().
if (UNLIKELY(!task || task.value().poison)) { if (UNLIKELY(!task || task.value().poison)) {
......
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
#include <folly/executors/EDFThreadPoolExecutor.h> #include <folly/executors/EDFThreadPoolExecutor.h>
namespace folly { namespace folly {
namespace {
constexpr folly::StringPiece executorName = "EDFThreadPoolExecutor";
}
class EDFThreadPoolExecutor::Task { class EDFThreadPoolExecutor::Task {
public: public:
...@@ -340,6 +343,7 @@ folly::Executor::KeepAlive<> EDFThreadPoolExecutor::deadlineExecutor( ...@@ -340,6 +343,7 @@ folly::Executor::KeepAlive<> EDFThreadPoolExecutor::deadlineExecutor(
void EDFThreadPoolExecutor::threadRun(ThreadPtr thread) { void EDFThreadPoolExecutor::threadRun(ThreadPtr thread) {
this->threadPoolHook_.registerThread(); this->threadPoolHook_.registerThread();
auto guard = folly::makeBlockingDisallowedGuard(executorName);
thread->startupBaton.post(); thread->startupBaton.post();
for (;;) { for (;;) {
......
...@@ -1002,3 +1002,47 @@ TEST(ThreadPoolExecutorTest, VirtualExecutorTestCPU) { ...@@ -1002,3 +1002,47 @@ TEST(ThreadPoolExecutorTest, VirtualExecutorTestCPU) {
TEST(ThreadPoolExecutorTest, VirtualExecutorTestEDF) { TEST(ThreadPoolExecutorTest, VirtualExecutorTestEDF) {
virtualExecutorTest<EDFThreadPoolExecutor>(); virtualExecutorTest<EDFThreadPoolExecutor>();
} }
// Test use of guard inside executors
template <class TPE>
static void currentThreadTest(folly::StringPiece executorName) {
folly::Optional<BlockingContext> blockingContext{};
TPE tpe(1);
tpe.add([&blockingContext]() { blockingContext = getBlockingContext(); });
tpe.join();
EXPECT_EQ(blockingContext->executorName, executorName);
}
// Test the nesting of the allowing guard
template <class TPE>
static void currentThreadTestDisabled(folly::StringPiece executorName) {
folly::Optional<BlockingContext> blockingContextAllowed{};
folly::Optional<BlockingContext> blockingContextDisallowed{};
TPE tpe(1);
tpe.add([&]() {
{
// Nest the guard that reallows blocking
auto guard = folly::makeBlockingAllowedGuard();
blockingContextAllowed = getBlockingContext();
}
blockingContextDisallowed = getBlockingContext();
});
tpe.join();
EXPECT_TRUE(!blockingContextAllowed.has_value());
EXPECT_EQ(blockingContextDisallowed->executorName, executorName);
}
TEST(ThreadPoolExecutorTest, CPUCurrentThreadExecutor) {
currentThreadTest<CPUThreadPoolExecutor>("CPUThreadPoolExecutor");
currentThreadTestDisabled<CPUThreadPoolExecutor>("CPUThreadPoolExecutor");
}
TEST(ThreadPoolExecutorTest, IOCurrentThreadExecutor) {
currentThreadTest<IOThreadPoolExecutor>("EventBase");
currentThreadTestDisabled<IOThreadPoolExecutor>("EventBase");
}
TEST(ThreadPoolExecutorTest, EDFCurrentThreadExecutor) {
currentThreadTest<EDFThreadPoolExecutor>("EDFThreadPoolExecutor");
currentThreadTestDisabled<EDFThreadPoolExecutor>("EDFThreadPoolExecutor");
}
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <folly/system/ThreadName.h> #include <folly/system/ThreadName.h>
namespace { namespace {
constexpr folly::StringPiece executorName = "EventBase";
class EventBaseBackend : public folly::EventBaseBackendBase { class EventBaseBackend : public folly::EventBaseBackendBase {
public: public:
EventBaseBackend(); EventBaseBackend();
...@@ -309,6 +311,7 @@ void EventBase::waitUntilRunning() { ...@@ -309,6 +311,7 @@ void EventBase::waitUntilRunning() {
// enters the event_base loop -- will only exit when forced to // enters the event_base loop -- will only exit when forced to
bool EventBase::loop() { bool EventBase::loop() {
auto guard = folly::makeBlockingDisallowedGuard(executorName);
return loopBody(); return loopBody();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment