proxygen
folly::FunctionScheduler Class Reference

#include <FunctionScheduler.h>

Classes

struct  LatencyDistribution
 
struct  RepeatFunc
 
struct  RunTimeOrder
 

Public Types

using IntervalDistributionFunc = Function< std::chrono::milliseconds()>
 
using NextRunTimeFunc = Function< std::chrono::steady_clock::time_point(std::chrono::steady_clock::time_point, std::chrono::steady_clock::time_point)>
 

Public Member Functions

 FunctionScheduler ()
 
 ~FunctionScheduler ()
 
void setSteady (bool steady)
 
void addFunction (Function< void()> &&cb, std::chrono::milliseconds interval, StringPiece nameID=StringPiece(), std::chrono::milliseconds startDelay=std::chrono::milliseconds(0))
 
void addFunction (Function< void()> &&cb, std::chrono::milliseconds interval, const LatencyDistribution &latencyDistr, StringPiece nameID=StringPiece(), std::chrono::milliseconds startDelay=std::chrono::milliseconds(0))
 
void addFunctionOnce (Function< void()> &&cb, StringPiece nameID=StringPiece(), std::chrono::milliseconds startDelay=std::chrono::milliseconds(0))
 
void addFunctionUniformDistribution (Function< void()> &&cb, std::chrono::milliseconds minInterval, std::chrono::milliseconds maxInterval, StringPiece nameID, std::chrono::milliseconds startDelay)
 
void addFunctionConsistentDelay (Function< void()> &&cb, std::chrono::milliseconds interval, StringPiece nameID=StringPiece(), std::chrono::milliseconds startDelay=std::chrono::milliseconds(0))
 
void addFunctionGenericDistribution (Function< void()> &&cb, IntervalDistributionFunc &&intervalFunc, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay)
 
void addFunctionGenericNextRunTimeFunctor (Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay)
 
bool cancelFunction (StringPiece nameID)
 
bool cancelFunctionAndWait (StringPiece nameID)
 
void cancelAllFunctions ()
 
void cancelAllFunctionsAndWait ()
 
bool resetFunctionTimer (StringPiece nameID)
 
bool start ()
 
bool shutdown ()
 
void setThreadName (StringPiece threadName)
 
template<typename RepeatFuncNextRunTimeFunc >
void addFunctionToHeapChecked (Function< void()> &&cb, RepeatFuncNextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, milliseconds startDelay, bool runOnce)
 

Private Types

typedef std::vector< std::unique_ptr< RepeatFunc > > FunctionHeap
 
typedef std::unordered_map< StringPiece, RepeatFunc *, HashFunctionMap
 

Private Member Functions

void run ()
 
void runOneFunction (std::unique_lock< std::mutex > &lock, std::chrono::steady_clock::time_point now)
 
void cancelFunction (const std::unique_lock< std::mutex > &lock, RepeatFunc *it)
 
void addFunctionToHeap (const std::unique_lock< std::mutex > &lock, std::unique_ptr< RepeatFunc > func)
 
template<typename RepeatFuncNextRunTimeFunc >
void addFunctionToHeapChecked (Function< void()> &&cb, RepeatFuncNextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
 
void addFunctionInternal (Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
 
void addFunctionInternal (Function< void()> &&cb, IntervalDistributionFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
 
bool cancelAllFunctionsWithLock (std::unique_lock< std::mutex > &lock)
 
bool cancelFunctionWithLock (std::unique_lock< std::mutex > &lock, StringPiece nameID)
 

Private Attributes

std::thread thread_
 
std::mutex mutex_
 
bool running_ {false}
 
FunctionHeap functions_
 
FunctionMap functionsMap_
 
RunTimeOrder fnCmp_
 
RepeatFunccurrentFunction_ {nullptr}
 
std::condition_variable runningCondvar_
 
std::string threadName_
 
bool steady_ {false}
 
bool cancellingCurrentFunction_ {false}
 

Detailed Description

Schedules any number of functions to run at various intervals. E.g.,

FunctionScheduler fs;

fs.addFunction([&] { LOG(INFO) << "tick..."; }, seconds(1), "ticker"); fs.addFunction(std::bind(&TestClass::doStuff, this), minutes(5), "stuff"); fs.start(); ........ fs.cancelFunction("ticker"); fs.addFunction([&] { LOG(INFO) << "tock..."; }, minutes(3), "tocker"); ........ fs.shutdown();

Note: the class uses only one thread - if you want to use more than one thread, either use multiple FunctionScheduler objects, or check out ThreadedRepeatingFunctionRunner.h for a much simpler contract of "run each function periodically in its own thread".

start() schedules the functions, while shutdown() terminates further scheduling.

Definition at line 54 of file FunctionScheduler.h.

Member Typedef Documentation

typedef std::vector<std::unique_ptr<RepeatFunc> > folly::FunctionScheduler::FunctionHeap
private

Definition at line 314 of file FunctionScheduler.h.

typedef std::unordered_map<StringPiece, RepeatFunc*, Hash> folly::FunctionScheduler::FunctionMap
private

Definition at line 315 of file FunctionScheduler.h.

using folly::FunctionScheduler::IntervalDistributionFunc = Function<std::chrono::milliseconds()>

A type alias for function that is called to determine the time interval for the next scheduled run.

Definition at line 154 of file FunctionScheduler.h.

using folly::FunctionScheduler::NextRunTimeFunc = Function<std::chrono::steady_clock::time_point( std::chrono::steady_clock::time_point, std::chrono::steady_clock::time_point)>

A type alias for function that returns the next run time, given the current run time and the current start time.

Definition at line 161 of file FunctionScheduler.h.

Constructor & Destructor Documentation

folly::FunctionScheduler::FunctionScheduler ( )

Definition at line 114 of file FunctionScheduler.cpp.

114 {}
folly::FunctionScheduler::~FunctionScheduler ( )

Member Function Documentation

void folly::FunctionScheduler::addFunction ( Function< void()> &&  cb,
std::chrono::milliseconds  interval,
StringPiece  nameID = StringPiece(),
std::chrono::milliseconds  startDelay = std::chrono::milliseconds(0) 
)

Adds a new function to the FunctionScheduler.

Functions will not be run until start() is called. When start() is called, each function will be run after its specified startDelay. Functions may also be added after start() has been called, in which case startDelay is still honored.

Throws an exception on error. In particular, each function must have a unique name–two functions cannot be added with the same name.

Referenced by folly::FunctionScheduler::LatencyDistribution::LatencyDistribution(), TEST(), and ~FunctionScheduler().

void folly::FunctionScheduler::addFunction ( Function< void()> &&  cb,
std::chrono::milliseconds  interval,
const LatencyDistribution latencyDistr,
StringPiece  nameID = StringPiece(),
std::chrono::milliseconds  startDelay = std::chrono::milliseconds(0) 
)
void folly::FunctionScheduler::addFunctionConsistentDelay ( Function< void()> &&  cb,
std::chrono::milliseconds  interval,
StringPiece  nameID = StringPiece(),
std::chrono::milliseconds  startDelay = std::chrono::milliseconds(0) 
)

Add a new function to the FunctionScheduler whose start times are attempted to be scheduled so that they are congruent modulo the interval. Note: The scheduling of the next run time happens right before the function invocation, so the first time a function takes more time than the interval, it will be reinvoked immediately.

Definition at line 183 of file FunctionScheduler.cpp.

References folly::gen::move, and folly::Range< Iter >::str().

Referenced by folly::FunctionScheduler::LatencyDistribution::LatencyDistribution(), and TEST().

187  {
189  std::move(cb),
190  ConsistentDelayFunctor(interval),
191  nameID.str(),
192  to<std::string>(interval.count(), "ms"),
193  startDelay,
194  false /*runOnce*/);
195 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void addFunctionInternal(Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
void folly::FunctionScheduler::addFunctionGenericDistribution ( Function< void()> &&  cb,
IntervalDistributionFunc &&  intervalFunc,
const std::string nameID,
const std::string intervalDescr,
std::chrono::milliseconds  startDelay 
)

Add a new function to the FunctionScheduler. The scheduling interval is determined by the interval distribution functor, which is called every time the next function execution is scheduled. This allows for supporting custom interval distribution algorithms in addition to built in constant interval; and Poisson and jitter distributions (

See also
FunctionScheduler::addFunction and
FunctionScheduler::addFunctionJitterInterval).

Definition at line 197 of file FunctionScheduler.cpp.

References folly::gen::move.

Referenced by TEST().

202  {
204  std::move(cb),
205  std::move(intervalFunc),
206  nameID,
207  intervalDescr,
208  startDelay,
209  false /*runOnce*/);
210 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void addFunctionInternal(Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
void folly::FunctionScheduler::addFunctionGenericNextRunTimeFunctor ( Function< void()> &&  cb,
NextRunTimeFunc &&  fn,
const std::string nameID,
const std::string intervalDescr,
std::chrono::milliseconds  startDelay 
)

Like addFunctionGenericDistribution, adds a new function to the FunctionScheduler, but the next run time is determined directly by the given functor, rather than by adding an interval.

Definition at line 212 of file FunctionScheduler.cpp.

References folly::gen::move.

217  {
219  std::move(cb),
220  std::move(fn),
221  nameID,
222  intervalDescr,
223  startDelay,
224  false /*runOnce*/);
225 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void addFunctionInternal(Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
void folly::FunctionScheduler::addFunctionInternal ( Function< void()> &&  cb,
NextRunTimeFunc &&  fn,
const std::string nameID,
const std::string intervalDescr,
std::chrono::milliseconds  startDelay,
bool  runOnce 
)
private
void folly::FunctionScheduler::addFunctionInternal ( Function< void()> &&  cb,
IntervalDistributionFunc &&  fn,
const std::string nameID,
const std::string intervalDescr,
std::chrono::milliseconds  startDelay,
bool  runOnce 
)
private
void folly::FunctionScheduler::addFunctionOnce ( Function< void()> &&  cb,
StringPiece  nameID = StringPiece(),
std::chrono::milliseconds  startDelay = std::chrono::milliseconds(0) 
)

Adds a new function to the FunctionScheduler to run only once.

Definition at line 154 of file FunctionScheduler.cpp.

References folly::gen::move, and folly::Range< Iter >::str().

Referenced by folly::FunctionScheduler::LatencyDistribution::LatencyDistribution(), and TEST().

157  {
159  std::move(cb),
160  ConstIntervalFunctor(milliseconds::zero()),
161  nameID.str(),
162  "once",
163  startDelay,
164  true /*runOnce*/);
165 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void addFunctionInternal(Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
void folly::FunctionScheduler::addFunctionToHeap ( const std::unique_lock< std::mutex > &  lock,
std::unique_ptr< RepeatFunc func 
)
private

Definition at line 551 of file FunctionScheduler.cpp.

References folly::gen::move, mutex_, and now().

553  {
554  // This function should only be called with mutex_ already locked.
555  DCHECK(lock.mutex() == &mutex_);
556  DCHECK(lock.owns_lock());
557 
558  functions_.push_back(std::move(func));
559  functionsMap_[functions_.back()->name] = functions_.back().get();
560  if (running_) {
561  functions_.back()->resetNextRunTime(steady_clock::now());
562  std::push_heap(functions_.begin(), functions_.end(), fnCmp_);
563  // Signal the running thread to wake up and see if it needs to change
564  // its current scheduling decision.
565  runningCondvar_.notify_one();
566  }
567 }
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::condition_variable runningCondvar_
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
template<typename RepeatFuncNextRunTimeFunc >
void folly::FunctionScheduler::addFunctionToHeapChecked ( Function< void()> &&  cb,
RepeatFuncNextRunTimeFunc &&  fn,
const std::string nameID,
const std::string intervalDescr,
milliseconds  startDelay,
bool  runOnce 
)

Definition at line 228 of file FunctionScheduler.cpp.

References addFunctionInternal(), folly::gen::move, mutex_, and string.

234  {
235  if (!cb) {
236  throw std::invalid_argument(
237  "FunctionScheduler: Scheduled function must be set");
238  }
239  if (!fn) {
240  throw std::invalid_argument(
241  "FunctionScheduler: "
242  "interval distribution or next run time function must be set");
243  }
244  if (startDelay < milliseconds::zero()) {
245  throw std::invalid_argument(
246  "FunctionScheduler: start delay must be non-negative");
247  }
248 
249  std::unique_lock<std::mutex> l(mutex_);
250  auto it = functionsMap_.find(nameID);
251  // check if the nameID is unique
252  if (it != functionsMap_.end() && it->second->isValid()) {
253  throw std::invalid_argument(to<std::string>(
254  "FunctionScheduler: a function named \"", nameID, "\" already exists"));
255  }
256 
257  if (currentFunction_ && currentFunction_->name == nameID) {
258  throw std::invalid_argument(to<std::string>(
259  "FunctionScheduler: a function named \"", nameID, "\" already exists"));
260  }
261 
263  l,
264  std::make_unique<RepeatFunc>(
265  std::move(cb),
266  std::forward<RepeatFuncNextRunTimeFunc>(fn),
267  nameID,
268  intervalDescr,
269  startDelay,
270  runOnce));
271 }
void addFunctionToHeap(const std::unique_lock< std::mutex > &lock, std::unique_ptr< RepeatFunc > func)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
template<typename RepeatFuncNextRunTimeFunc >
void folly::FunctionScheduler::addFunctionToHeapChecked ( Function< void()> &&  cb,
RepeatFuncNextRunTimeFunc &&  fn,
const std::string nameID,
const std::string intervalDescr,
std::chrono::milliseconds  startDelay,
bool  runOnce 
)
private
void folly::FunctionScheduler::addFunctionUniformDistribution ( Function< void()> &&  cb,
std::chrono::milliseconds  minInterval,
std::chrono::milliseconds  maxInterval,
StringPiece  nameID,
std::chrono::milliseconds  startDelay 
)

Add a new function to the FunctionScheduler with the time interval being distributed uniformly within the given interval [minInterval, maxInterval].

Definition at line 167 of file FunctionScheduler.cpp.

References folly::gen::move, and folly::Range< Iter >::str().

Referenced by folly::FunctionScheduler::LatencyDistribution::LatencyDistribution(), and TEST().

172  {
174  std::move(cb),
175  UniformDistributionFunctor(minInterval, maxInterval),
176  nameID.str(),
177  to<std::string>(
178  "[", minInterval.count(), " , ", maxInterval.count(), "] ms"),
179  startDelay,
180  false /*runOnce*/);
181 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void addFunctionInternal(Function< void()> &&cb, NextRunTimeFunc &&fn, const std::string &nameID, const std::string &intervalDescr, std::chrono::milliseconds startDelay, bool runOnce)
void folly::FunctionScheduler::cancelAllFunctions ( )

All functions registered will be canceled.

Definition at line 362 of file FunctionScheduler.cpp.

References mutex_.

362  {
363  std::unique_lock<std::mutex> l(mutex_);
365 }
bool cancelAllFunctionsWithLock(std::unique_lock< std::mutex > &lock)
void folly::FunctionScheduler::cancelAllFunctionsAndWait ( )

Definition at line 367 of file FunctionScheduler.cpp.

References mutex_.

Referenced by TEST().

367  {
368  std::unique_lock<std::mutex> l(mutex_);
370  runningCondvar_.wait(l, [this]() { return !cancellingCurrentFunction_; });
371  }
372 }
std::condition_variable runningCondvar_
bool cancelAllFunctionsWithLock(std::unique_lock< std::mutex > &lock)
bool folly::FunctionScheduler::cancelAllFunctionsWithLock ( std::unique_lock< std::mutex > &  lock)
private

Definition at line 350 of file FunctionScheduler.cpp.

351  {
352  CHECK_EQ(lock.owns_lock(), true);
353  functions_.clear();
354  functionsMap_.clear();
355  if (currentFunction_) {
357  }
358  currentFunction_ = nullptr;
360 }
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
bool folly::FunctionScheduler::cancelFunction ( StringPiece  nameID)

Cancels the function with the specified name, so it will no longer be run.

Returns false if no function exists with the specified name.

Definition at line 310 of file FunctionScheduler.cpp.

References mutex_.

Referenced by TEST().

310  {
311  std::unique_lock<std::mutex> l(mutex_);
312  if (cancelFunctionWithLock(l, nameID)) {
313  return true;
314  }
315  auto it = functionsMap_.find(nameID);
316  if (it != functionsMap_.end() && it->second->isValid()) {
317  cancelFunction(l, it->second);
318  return true;
319  }
320 
321  return false;
322 }
bool cancelFunctionWithLock(std::unique_lock< std::mutex > &lock, StringPiece nameID)
bool cancelFunction(StringPiece nameID)
void folly::FunctionScheduler::cancelFunction ( const std::unique_lock< std::mutex > &  lock,
RepeatFunc it 
)
private

Definition at line 340 of file FunctionScheduler.cpp.

References folly::FunctionScheduler::RepeatFunc::cancel(), mutex_, and folly::FunctionScheduler::RepeatFunc::name.

342  {
343  // This function should only be called with mutex_ already locked.
344  DCHECK(l.mutex() == &mutex_);
345  DCHECK(l.owns_lock());
346  functionsMap_.erase(it->name);
347  it->cancel();
348 }
bool folly::FunctionScheduler::cancelFunctionAndWait ( StringPiece  nameID)

Definition at line 324 of file FunctionScheduler.cpp.

References mutex_.

Referenced by TEST().

324  {
325  std::unique_lock<std::mutex> l(mutex_);
326 
327  if (cancelFunctionWithLock(l, nameID)) {
328  runningCondvar_.wait(l, [this]() { return !cancellingCurrentFunction_; });
329  return true;
330  }
331 
332  auto it = functionsMap_.find(nameID);
333  if (it != functionsMap_.end() && it->second->isValid()) {
334  cancelFunction(l, it->second);
335  return true;
336  }
337  return false;
338 }
bool cancelFunctionWithLock(std::unique_lock< std::mutex > &lock, StringPiece nameID)
std::condition_variable runningCondvar_
bool cancelFunction(StringPiece nameID)
bool folly::FunctionScheduler::cancelFunctionWithLock ( std::unique_lock< std::mutex > &  lock,
StringPiece  nameID 
)
private

Definition at line 295 of file FunctionScheduler.cpp.

297  {
298  CHECK_EQ(lock.owns_lock(), true);
299  if (currentFunction_ && currentFunction_->name == nameID) {
301  // This function is currently being run. Clear currentFunction_
302  // The running thread will see this and won't reschedule the function.
303  currentFunction_ = nullptr;
305  return true;
306  }
307  return false;
308 }
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
bool folly::FunctionScheduler::resetFunctionTimer ( StringPiece  nameID)

Resets the specified function's timer. When resetFunctionTimer is called, the specified function's timer will be reset with the same parameters it was passed initially, including its startDelay. If the startDelay was 0, the function will be invoked immediately.

Returns false if no function exists with the specified name.

Definition at line 374 of file FunctionScheduler.cpp.

References mutex_, and now().

Referenced by TEST().

374  {
375  std::unique_lock<std::mutex> l(mutex_);
376  if (currentFunction_ && currentFunction_->name == nameID) {
378  return false;
379  }
381  return true;
382  }
383 
384  // Since __adjust_heap() isn't a part of the standard API, there's no way to
385  // fix the heap ordering if we adjust the key (nextRunTime) for the existing
386  // RepeatFunc. Instead, we just cancel it and add an identical object.
387  auto it = functionsMap_.find(nameID);
388  if (it != functionsMap_.end() && it->second->isValid()) {
389  if (running_) {
390  it->second->resetNextRunTime(steady_clock::now());
391  std::make_heap(functions_.begin(), functions_.end(), fnCmp_);
392  runningCondvar_.notify_one();
393  }
394  return true;
395  }
396  return false;
397 }
std::chrono::steady_clock::time_point now()
std::condition_variable runningCondvar_
void resetNextRunTime(std::chrono::steady_clock::time_point curTime)
void folly::FunctionScheduler::run ( )
private

Definition at line 438 of file FunctionScheduler.cpp.

References folly::lock(), mutex_, now(), and folly::setThreadName().

438  {
439  std::unique_lock<std::mutex> lock(mutex_);
440 
441  if (!threadName_.empty()) {
443  }
444 
445  while (running_) {
446  // If we have nothing to run, wait until a function is added or until we
447  // are stopped.
448  if (functions_.empty()) {
449  runningCondvar_.wait(lock);
450  continue;
451  }
452 
453  auto now = steady_clock::now();
454 
455  // Move the next function to run to the end of functions_
456  std::pop_heap(functions_.begin(), functions_.end(), fnCmp_);
457 
458  // Check to see if the function was cancelled.
459  // If so, just remove it and continue around the loop.
460  if (!functions_.back()->isValid()) {
461  functions_.pop_back();
462  continue;
463  }
464 
465  auto sleepTime = functions_.back()->getNextRunTime() - now;
466  if (sleepTime < milliseconds::zero()) {
467  // We need to run this function now
469  runningCondvar_.notify_all();
470  } else {
471  // Re-add the function to the heap, and wait until we actually
472  // need to run it.
473  std::push_heap(functions_.begin(), functions_.end(), fnCmp_);
474  runningCondvar_.wait_for(lock, sleepTime);
475  }
476  }
477 }
std::chrono::steady_clock::time_point now()
std::condition_variable runningCondvar_
void runOneFunction(std::unique_lock< std::mutex > &lock, std::chrono::steady_clock::time_point now)
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
bool setThreadName(std::thread::id tid, StringPiece name)
Definition: ThreadName.cpp:109
void folly::FunctionScheduler::runOneFunction ( std::unique_lock< std::mutex > &  lock,
std::chrono::steady_clock::time_point  now 
)
private

Definition at line 479 of file FunctionScheduler.cpp.

References folly::exceptionStr(), folly::gen::move, and mutex_.

481  {
482  DCHECK(lock.mutex() == &mutex_);
483  DCHECK(lock.owns_lock());
484 
485  // The function to run will be at the end of functions_ already.
486  //
487  // Fully remove it from functions_ now.
488  // We need to release mutex_ while we invoke this function, and we need to
489  // maintain the heap property on functions_ while mutex_ is unlocked.
490  auto func = std::move(functions_.back());
491  functions_.pop_back();
492  if (!func->cb) {
493  VLOG(5) << func->name << "function has been canceled while waiting";
494  return;
495  }
496  currentFunction_ = func.get();
497  // Update the function's next run time.
498  if (steady_) {
499  // This allows scheduler to catch up
500  func->setNextRunTimeSteady();
501  } else {
502  // Note that we set nextRunTime based on the current time where we started
503  // the function call, rather than the time when the function finishes.
504  // This ensures that we call the function once every time interval, as
505  // opposed to waiting time interval seconds between calls. (These can be
506  // different if the function takes a significant amount of time to run.)
507  func->setNextRunTimeStrict(now);
508  }
509 
510  // Release the lock while we invoke the user's function
511  lock.unlock();
512 
513  // Invoke the function
514  try {
515  VLOG(5) << "Now running " << func->name;
516  func->cb();
517  } catch (const std::exception& ex) {
518  LOG(ERROR) << "Error running the scheduled function <" << func->name
519  << ">: " << exceptionStr(ex);
520  }
521 
522  // Re-acquire the lock
523  lock.lock();
524 
525  if (!currentFunction_) {
526  // The function was cancelled while we were running it.
527  // We shouldn't reschedule it;
529  return;
530  }
531  if (currentFunction_->runOnce) {
532  // Don't reschedule if the function only needed to run once.
534  currentFunction_ = nullptr;
535  return;
536  }
537 
538  // Re-insert the function into our functions_ heap.
539  // We only maintain the heap property while running_ is set. (running_ may
540  // have been cleared while we were invoking the user's function.)
541  functions_.push_back(std::move(func));
542 
543  // Clear currentFunction_
544  currentFunction_ = nullptr;
545 
546  if (running_) {
547  std::push_heap(functions_.begin(), functions_.end(), fnCmp_);
548  }
549 }
fbstring exceptionStr(const std::exception &e)
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
void folly::FunctionScheduler::setSteady ( bool  steady)
inline

By default steady is false, meaning schedules may lag behind overtime. This could be due to long running tasks or time drift because of randomness in thread wakeup time. By setting steady to true, FunctionScheduler will attempt to catch up. i.e. more like a cronjob

NOTE: it's only safe to set this before calling start()

Definition at line 68 of file FunctionScheduler.h.

References steady_.

Referenced by TEST().

68  {
69  steady_ = steady;
70  }
void folly::FunctionScheduler::setThreadName ( StringPiece  threadName)

Set the name of the worker thread.

Definition at line 569 of file FunctionScheduler.cpp.

References mutex_, and folly::Range< Iter >::str().

569  {
570  std::unique_lock<std::mutex> l(mutex_);
571  threadName_ = threadName.str();
572 }
bool folly::FunctionScheduler::shutdown ( )

Stops the FunctionScheduler.

It may be restarted later by calling start() again. Returns false if the scheduler was not running.

Definition at line 424 of file FunctionScheduler.cpp.

References g(), and mutex_.

Referenced by TEST().

424  {
425  {
426  std::lock_guard<std::mutex> g(mutex_);
427  if (!running_) {
428  return false;
429  }
430 
431  running_ = false;
432  runningCondvar_.notify_one();
433  }
434  thread_.join();
435  return true;
436 }
std::condition_variable runningCondvar_
g_t g(f_t)
bool folly::FunctionScheduler::start ( )

Starts the scheduler.

Returns false if the scheduler was already running.

Definition at line 399 of file FunctionScheduler.cpp.

References f, mutex_, now(), and folly::run().

Referenced by TEST().

399  {
400  std::unique_lock<std::mutex> l(mutex_);
401  if (running_) {
402  return false;
403  }
404 
405  VLOG(1) << "Starting FunctionScheduler with " << functions_.size()
406  << " functions.";
407  auto now = steady_clock::now();
408  // Reset the next run time. for all functions.
409  // note: this is needed since one can shutdown() and start() again
410  for (const auto& f : functions_) {
411  f->resetNextRunTime(now);
412  VLOG(1) << " - func: " << (f->name.empty() ? "(anon)" : f->name.c_str())
413  << ", period = " << f->intervalDescr
414  << ", delay = " << f->startDelay.count() << "ms";
415  }
416  std::make_heap(functions_.begin(), functions_.end(), fnCmp_);
417 
418  thread_ = std::thread([&] { this->run(); });
419  running_ = true;
420 
421  return true;
422 }
auto f
std::chrono::steady_clock::time_point now()

Member Data Documentation

bool folly::FunctionScheduler::cancellingCurrentFunction_ {false}
private

Definition at line 378 of file FunctionScheduler.h.

RepeatFunc* folly::FunctionScheduler::currentFunction_ {nullptr}
private

Definition at line 370 of file FunctionScheduler.h.

RunTimeOrder folly::FunctionScheduler::fnCmp_
private

Definition at line 366 of file FunctionScheduler.h.

FunctionHeap folly::FunctionScheduler::functions_
private

Definition at line 364 of file FunctionScheduler.h.

FunctionMap folly::FunctionScheduler::functionsMap_
private

Definition at line 365 of file FunctionScheduler.h.

std::mutex folly::FunctionScheduler::mutex_
private

Definition at line 359 of file FunctionScheduler.h.

bool folly::FunctionScheduler::running_ {false}
private

Definition at line 360 of file FunctionScheduler.h.

std::condition_variable folly::FunctionScheduler::runningCondvar_
private

Definition at line 374 of file FunctionScheduler.h.

bool folly::FunctionScheduler::steady_ {false}
private

Definition at line 377 of file FunctionScheduler.h.

Referenced by setSteady().

std::thread folly::FunctionScheduler::thread_
private

Definition at line 356 of file FunctionScheduler.h.

std::string folly::FunctionScheduler::threadName_
private

Definition at line 376 of file FunctionScheduler.h.


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