ThreadedRepeatingFunctionRunnerTest.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Copyright 2013-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/portability/GTest.h>
  18. #include <atomic>
  19. using namespace std;
  20. struct Foo {
  21. explicit Foo(std::atomic<int>& d) : data(d) {}
  22. ~Foo() {
  23. runner_.stop();
  24. }
  25. void start() {
  26. runner_.add("Foo", [this]() {
  27. ++data;
  28. return std::chrono::seconds(0);
  29. });
  30. }
  31. std::atomic<int>& data;
  32. folly::ThreadedRepeatingFunctionRunner runner_; // Must be declared last
  33. };
  34. struct FooLongSleep {
  35. explicit FooLongSleep(std::atomic<int>& d) : data(d) {}
  36. ~FooLongSleep() {
  37. runner_.stop();
  38. data.store(-1);
  39. }
  40. void start() {
  41. runner_.add("FooLongSleep", [this]() {
  42. data.store(1);
  43. return 1000h; // Test would time out if we waited
  44. });
  45. }
  46. std::atomic<int>& data;
  47. folly::ThreadedRepeatingFunctionRunner runner_; // Must be declared last
  48. };
  49. TEST(TestThreadedRepeatingFunctionRunner, HandleBackgroundLoop) {
  50. std::atomic<int> data(0);
  51. {
  52. Foo f(data);
  53. EXPECT_EQ(0, data.load());
  54. f.start(); // Runs increment thread in background
  55. while (data.load() == 0) {
  56. /* sleep override */ this_thread::sleep_for(chrono::milliseconds(10));
  57. }
  58. }
  59. // The increment thread should have been destroyed
  60. auto prev_val = data.load();
  61. /* sleep override */ this_thread::sleep_for(chrono::milliseconds(100));
  62. EXPECT_EQ(data.load(), prev_val);
  63. }
  64. TEST(TestThreadedRepeatingFunctionRunner, HandleLongSleepingThread) {
  65. std::atomic<int> data(0);
  66. {
  67. FooLongSleep f(data);
  68. EXPECT_EQ(0, data.load());
  69. f.start();
  70. while (data.load() == 0) {
  71. /* sleep override */ this_thread::sleep_for(chrono::milliseconds(10));
  72. }
  73. EXPECT_EQ(1, data.load());
  74. }
  75. // Foo should have been destroyed, which stopped the thread!
  76. EXPECT_EQ(-1, data.load());
  77. }