proxygen
folly::test::ManualSchedule Class Reference

Public Member Functions

 ManualSchedule ()=default
 
 ~ManualSchedule ()
 
void setCallback (std::function< void()> callback)
 
void removeCallbacks ()
 
void wait (int id)
 
void post (int id)
 

Static Public Member Functions

static void beforeSharedAccess ()
 
static void afterSharedAccess (bool)
 

Private Attributes

Synchronized< std::unordered_map< std::thread::id, std::function< void()> > > callbacks_
 
Synchronized< std::unordered_map< int, folly::Baton<> > > batons_
 

Static Private Attributes

static Synchronized< std::unordered_map< std::thread::id, ManualSchedule * > > schedules_
 

Detailed Description

Like DeterministicSchedule, but allows setting callbacks that can be run for the current thread when an atomic access occurs, and after. This allows us to construct thread interleavings by hand

Constructing a ManualSchedule is required to ensure that we maintain per-test state for threads

This can also be used to order thread movement, as an alternative to maintaining condition variables and/or semaphores for the purposes of testing, for example

auto one = std::thread{[&]() { schedule.wait(1); two(); schedule.post(2); }};

auto two = std::thread{[&]() { one(); schedule.post(1); schedule.wait(2); three(); }};

The code above is guaranteed to call one(), then two(), and then three()

Definition at line 58 of file DistributedMutexTest.cpp.

Constructor & Destructor Documentation

folly::test::ManualSchedule::ManualSchedule ( )
default
folly::test::ManualSchedule::~ManualSchedule ( )
inline

Definition at line 61 of file DistributedMutexTest.cpp.

References for_each().

61  {
62  // delete this schedule from the global map
63  auto schedules = schedules_.wlock();
64  for_each(*schedules, [&](auto& schedule, auto, auto iter) {
65  if (schedule.second == this) {
66  schedules->erase(iter);
67  }
68  });
69  }
static Synchronized< std::unordered_map< std::thread::id, ManualSchedule * > > schedules_
FOLLY_CPP14_CONSTEXPR Func for_each(Sequence &&sequence, Func func)
Definition: Foreach-inl.h:314

Member Function Documentation

static void folly::test::ManualSchedule::afterSharedAccess ( bool  )
inlinestatic

Definition at line 95 of file DistributedMutexTest.cpp.

95  {
97  }
static void folly::test::ManualSchedule::beforeSharedAccess ( )
inlinestatic

These will be invoked by DeterministicAtomic to signal atomic access before and after the operation

Definition at line 75 of file DistributedMutexTest.cpp.

References folly::get_ptr(), and folly::kIsDebug.

75  {
76  if (folly::kIsDebug) {
77  auto id = std::this_thread::get_id();
78 
79  // get the schedule assigned for the current thread, if one exists,
80  // otherwise proceed as normal
81  auto schedule = get_ptr(*schedules_.wlock(), id);
82  if (!schedule) {
83  return;
84  }
85 
86  // now try and get the callbacks for this thread, if there is a callback
87  // registered for the test, it must mean that we have a callback
88  auto callback = get_ptr((*(*schedule)->callbacks_.wlock()), id);
89  if (!callback) {
90  return;
91  }
92  (*callback)();
93  }
94  }
const Map::mapped_type * get_ptr(const Map &map, const Key &key)
Definition: MapUtil.h:169
static Synchronized< std::unordered_map< std::thread::id, ManualSchedule * > > schedules_
constexpr auto kIsDebug
Definition: Portability.h:264
void folly::test::ManualSchedule::post ( int  id)
inline

Definition at line 125 of file DistributedMutexTest.cpp.

References folly::kIsDebug.

125  {
126  if (folly::kIsDebug) {
127  auto& baton = (*batons_.wlock())[id];
128  baton.post();
129  }
130  }
constexpr auto kIsDebug
Definition: Portability.h:264
Synchronized< std::unordered_map< int, folly::Baton<> > > batons_
void folly::test::ManualSchedule::removeCallbacks ( )
inline

Delete the callback set for this thread on atomic accesses

Definition at line 112 of file DistributedMutexTest.cpp.

112  {
113  callbacks_.wlock()->erase(std::this_thread::get_id());
114  }
Synchronized< std::unordered_map< std::thread::id, std::function< void()> > > callbacks_
void folly::test::ManualSchedule::setCallback ( std::function< void()>  callback)
inline

Set a callback that will be called on every subsequent atomic access. This will be invoked before and after every atomic access, for the thread that called setCallback

Definition at line 104 of file DistributedMutexTest.cpp.

Referenced by folly::TEST().

104  {
105  schedules_.wlock()->insert({std::this_thread::get_id(), this});
106  callbacks_.wlock()->insert({std::this_thread::get_id(), callback});
107  }
static Synchronized< std::unordered_map< std::thread::id, ManualSchedule * > > schedules_
Synchronized< std::unordered_map< std::thread::id, std::function< void()> > > callbacks_
void folly::test::ManualSchedule::wait ( int  id)
inline

wait() and post() for easy testing

Definition at line 119 of file DistributedMutexTest.cpp.

References folly::kIsDebug.

119  {
120  if (folly::kIsDebug) {
121  auto& baton = (*batons_.wlock())[id];
122  baton.wait();
123  }
124  }
constexpr auto kIsDebug
Definition: Portability.h:264
Synchronized< std::unordered_map< int, folly::Baton<> > > batons_

Member Data Documentation

Synchronized<std::unordered_map<int, folly::Baton<> > > folly::test::ManualSchedule::batons_
private

Definition at line 141 of file DistributedMutexTest.cpp.

Synchronized<std::unordered_map<std::thread::id, std::function<void()> > > folly::test::ManualSchedule::callbacks_
private

Definition at line 138 of file DistributedMutexTest.cpp.

Synchronized< std::unordered_map< std::thread::id, ManualSchedule * > > folly::test::ManualSchedule::schedules_
staticprivate

Definition at line 135 of file DistributedMutexTest.cpp.


The documentation for this class was generated from the following file: