ThreadedRepeatingFunctionRunner.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/experimental/ThreadedRepeatingFunctionRunner.h>
  17. #include <folly/system/ThreadName.h>
  18. #include <glog/logging.h>
  19. #include <iostream>
  20. namespace folly {
  21. ThreadedRepeatingFunctionRunner::ThreadedRepeatingFunctionRunner() {}
  22. ThreadedRepeatingFunctionRunner::~ThreadedRepeatingFunctionRunner() {
  23. if (stopImpl()) {
  24. LOG(ERROR)
  25. << "ThreadedRepeatingFunctionRunner::stop() should already have been "
  26. << "called, since we are now in the Runner's destructor. This is "
  27. << "because it means that its threads may be accessing object state "
  28. << "that was already destroyed -- e.g. members that were declared "
  29. << "after the ThreadedRepeatingFunctionRunner.";
  30. }
  31. }
  32. void ThreadedRepeatingFunctionRunner::stop() {
  33. stopImpl();
  34. }
  35. bool ThreadedRepeatingFunctionRunner::stopImpl() {
  36. {
  37. std::unique_lock<std::mutex> lock(stopMutex_);
  38. if (stopping_) {
  39. return false; // Do nothing if stop() is called twice.
  40. }
  41. stopping_ = true;
  42. }
  43. stopCv_.notify_all();
  44. for (auto& t : threads_) {
  45. t.join();
  46. }
  47. return true;
  48. }
  49. void ThreadedRepeatingFunctionRunner::add(
  50. std::string name,
  51. RepeatingFn fn,
  52. std::chrono::milliseconds initialSleep) {
  53. threads_.emplace_back([name = std::move(name),
  54. fn = std::move(fn),
  55. initialSleep,
  56. this]() mutable {
  57. setThreadName(name);
  58. executeInLoop(std::move(fn), initialSleep);
  59. });
  60. }
  61. bool ThreadedRepeatingFunctionRunner::waitFor(
  62. std::chrono::milliseconds duration) noexcept {
  63. using clock = std::chrono::steady_clock;
  64. const auto deadline = clock::now() + duration;
  65. std::unique_lock<std::mutex> lock(stopMutex_);
  66. stopCv_.wait_until(
  67. lock, deadline, [&] { return stopping_ || clock::now() > deadline; });
  68. return !stopping_;
  69. }
  70. void ThreadedRepeatingFunctionRunner::executeInLoop(
  71. RepeatingFn fn,
  72. std::chrono::milliseconds initialSleep) noexcept {
  73. auto duration = initialSleep;
  74. while (waitFor(duration)) {
  75. duration = fn();
  76. }
  77. }
  78. } // namespace folly