Commit 481a93de authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

Move DeterministicSchedule TLState to the source

Summary: [Folly] Move `DeterministicSchedule` helper alias `TLState` to the source, and outline all uses into the source.

Reviewed By: nbronson, luciang

Differential Revision: D23157071

fbshipit-source-id: 957576a61a796f46da781e02419a1229e681d4c1
parent 0b3d9d21
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <utility> #include <utility>
#include <folly/Random.h> #include <folly/Random.h>
#include <folly/SingletonThreadLocal.h>
namespace folly { namespace folly {
namespace test { namespace test {
...@@ -116,6 +117,30 @@ void ThreadSyncVar::acq_rel() { ...@@ -116,6 +117,30 @@ void ThreadSyncVar::acq_rel() {
order_.sync(threadInfo.acqRelOrder_); order_.sync(threadInfo.acqRelOrder_);
} }
namespace {
struct PerThreadState {
// delete the constructors and assignment operators for sanity
//
// but... we can't delete the move constructor and assignment operators
// because those are required before C++17 in the implementation of
// SingletonThreadLocal
PerThreadState(const PerThreadState&) = delete;
PerThreadState& operator=(const PerThreadState&) = delete;
PerThreadState(PerThreadState&&) = default;
PerThreadState& operator=(PerThreadState&&) = default;
PerThreadState() = default;
Sem* sem{nullptr};
DeterministicSchedule* sched{nullptr};
bool exiting{false};
DSchedThreadId threadId{};
AuxAct aux_act{};
};
using TLState = SingletonThreadLocal<PerThreadState>;
} // namespace
DeterministicSchedule::DeterministicSchedule( DeterministicSchedule::DeterministicSchedule(
std::function<size_t(size_t)> scheduler) std::function<size_t(size_t)> scheduler)
: scheduler_(std::move(scheduler)), nextThreadId_(0), step_(0) { : scheduler_(std::move(scheduler)), nextThreadId_(0), step_(0) {
...@@ -200,6 +225,27 @@ struct UniformSubset { ...@@ -200,6 +225,27 @@ struct UniformSubset {
} }
}; };
bool DeterministicSchedule::isCurrentThreadExiting() {
auto& tls = TLState::get();
return tls.exiting;
}
bool DeterministicSchedule::isActive() {
auto& tls = TLState::get();
return tls.sched != nullptr;
}
DSchedThreadId DeterministicSchedule::getThreadId() {
auto& tls = TLState::get();
assert(tls.sched != nullptr);
return tls.threadId;
}
DeterministicSchedule* DeterministicSchedule::getCurrentSchedule() {
auto& tls = TLState::get();
return tls.sched;
}
std::function<size_t(size_t)> std::function<size_t(size_t)>
DeterministicSchedule::uniformSubset(uint64_t seed, size_t n, size_t m) { DeterministicSchedule::uniformSubset(uint64_t seed, size_t n, size_t m) {
auto gen = std::make_shared<UniformSubset>(seed, n, m); auto gen = std::make_shared<UniformSubset>(seed, n, m);
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <vector> #include <vector>
#include <folly/ScopeGuard.h> #include <folly/ScopeGuard.h>
#include <folly/SingletonThreadLocal.h>
#include <folly/concurrency/CacheLocality.h> #include <folly/concurrency/CacheLocality.h>
#include <folly/detail/Futex.h> #include <folly/detail/Futex.h>
#include <folly/synchronization/detail/AtomicUtils.h> #include <folly/synchronization/detail/AtomicUtils.h>
...@@ -199,8 +198,7 @@ class DeterministicSchedule { ...@@ -199,8 +198,7 @@ class DeterministicSchedule {
static inline std::thread thread(Func&& func, Args&&... args) { static inline std::thread thread(Func&& func, Args&&... args) {
// TODO: maybe future versions of gcc will allow forwarding to thread // TODO: maybe future versions of gcc will allow forwarding to thread
atomic_thread_fence(std::memory_order_seq_cst); atomic_thread_fence(std::memory_order_seq_cst);
auto& tls = TLState::get(); auto sched = getCurrentSchedule();
auto sched = tls.sched;
auto sem = sched ? sched->beforeThreadCreate() : nullptr; auto sem = sched ? sched->beforeThreadCreate() : nullptr;
auto child = std::thread( auto child = std::thread(
[=](Args... a) { [=](Args... a) {
...@@ -278,49 +276,22 @@ class DeterministicSchedule { ...@@ -278,49 +276,22 @@ class DeterministicSchedule {
/** Returns true if the current thread has already completed /** Returns true if the current thread has already completed
* the thread function, for example if the thread is executing * the thread function, for example if the thread is executing
* thread local destructors. */ * thread local destructors. */
static bool isCurrentThreadExiting() { static bool isCurrentThreadExiting();
auto& tls = TLState::get();
return tls.exiting;
}
/** Add sem back into sems_ */ /** Add sem back into sems_ */
static void reschedule(Sem* sem); static void reschedule(Sem* sem);
static bool isActive() { static bool isActive();
auto& tls = TLState::get();
return tls.sched != nullptr;
}
static DSchedThreadId getThreadId() { static DSchedThreadId getThreadId();
auto& tls = TLState::get();
assert(tls.sched != nullptr);
return tls.threadId;
}
static ThreadInfo& getCurrentThreadInfo(); static ThreadInfo& getCurrentThreadInfo();
static void atomic_thread_fence(std::memory_order mo); static void atomic_thread_fence(std::memory_order mo);
private: private:
struct PerThreadState { static DeterministicSchedule* getCurrentSchedule();
// delete the constructors and assignment operators for sanity
//
// but... we can't delete the move constructor and assignment operators
// because those are required before C++17 in the implementation of
// SingletonThreadLocal
PerThreadState(const PerThreadState&) = delete;
PerThreadState& operator=(const PerThreadState&) = delete;
PerThreadState(PerThreadState&&) = default;
PerThreadState& operator=(PerThreadState&&) = default;
PerThreadState() = default;
Sem* sem{nullptr};
DeterministicSchedule* sched{nullptr};
bool exiting{false};
DSchedThreadId threadId{};
AuxAct aux_act{};
};
using TLState = SingletonThreadLocal<PerThreadState>;
static AuxChk aux_chk; static AuxChk aux_chk;
std::function<size_t(size_t)> scheduler_; std::function<size_t(size_t)> scheduler_;
......
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