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