thread_pool_test.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2018 The Cartographer Authors
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 
18 
19 #include <vector>
20 
22 #include "gtest/gtest.h"
23 
24 namespace cartographer {
25 namespace common {
26 namespace {
27 
28 class Receiver {
29  public:
30  void Receive(int number) {
31  Mutex::Locker locker(&mutex_);
32  received_numbers_.push_back(number);
33  }
34 
35  void WaitForNumberSequence(const std::vector<int>& expected_numbers) {
36  common::MutexLocker locker(&mutex_);
37  locker.Await([this, &expected_numbers]() REQUIRES(mutex_) {
38  return (received_numbers_.size() >= expected_numbers.size());
39  });
40  EXPECT_EQ(expected_numbers, received_numbers_);
41  }
42 
43  Mutex mutex_;
44  std::vector<int> received_numbers_ GUARDED_BY(mutex_);
45 };
46 
47 TEST(ThreadPoolTest, RunTask) {
48  ThreadPool pool(1);
49  Receiver receiver;
50  auto task = common::make_unique<Task>();
51  task->SetWorkItem([&receiver]() { receiver.Receive(1); });
52  pool.Schedule(std::move(task));
53  receiver.WaitForNumberSequence({1});
54 }
55 
56 TEST(ThreadPoolTest, ManyTasks) {
57  for (int a = 0; a < 5; ++a) {
58  ThreadPool pool(3);
59  Receiver receiver;
60  int kNumTasks = 10;
61  for (int i = 0; i < kNumTasks; ++i) {
62  auto task = common::make_unique<Task>();
63  task->SetWorkItem([&receiver]() { receiver.Receive(1); });
64  pool.Schedule(std::move(task));
65  }
66  receiver.WaitForNumberSequence(std::vector<int>(kNumTasks, 1));
67  }
68 }
69 
70 TEST(ThreadPoolTest, RunWithDependency) {
71  ThreadPool pool(2);
72  Receiver receiver;
73  auto task_2 = common::make_unique<Task>();
74  task_2->SetWorkItem([&receiver]() { receiver.Receive(2); });
75  auto task_1 = common::make_unique<Task>();
76  task_1->SetWorkItem([&receiver]() { receiver.Receive(1); });
77  auto weak_task_1 = pool.Schedule(std::move(task_1));
78  task_2->AddDependency(weak_task_1);
79  pool.Schedule(std::move(task_2));
80  receiver.WaitForNumberSequence({1, 2});
81 }
82 
83 TEST(ThreadPoolTest, RunWithOutOfScopeDependency) {
84  ThreadPool pool(2);
85  Receiver receiver;
86  auto task_2 = common::make_unique<Task>();
87  task_2->SetWorkItem([&receiver]() { receiver.Receive(2); });
88  {
89  auto task_1 = common::make_unique<Task>();
90  task_1->SetWorkItem([&receiver]() { receiver.Receive(1); });
91  auto weak_task_1 = pool.Schedule(std::move(task_1));
92  task_2->AddDependency(weak_task_1);
93  }
94  pool.Schedule(std::move(task_2));
95  receiver.WaitForNumberSequence({1, 2});
96 }
97 
98 TEST(ThreadPoolTest, ManyDependencies) {
99  for (int a = 0; a < 5; ++a) {
100  ThreadPool pool(5);
101  Receiver receiver;
102  int kNumDependencies = 10;
103  auto task = common::make_unique<Task>();
104  task->SetWorkItem([&receiver]() { receiver.Receive(1); });
105  for (int i = 0; i < kNumDependencies; ++i) {
106  auto dependency_task = common::make_unique<Task>();
107  dependency_task->SetWorkItem([]() {});
108  task->AddDependency(pool.Schedule(std::move(dependency_task)));
109  }
110  pool.Schedule(std::move(task));
111  receiver.WaitForNumberSequence({1});
112  }
113 }
114 
115 TEST(ThreadPoolTest, ManyDependants) {
116  for (int a = 0; a < 5; ++a) {
117  ThreadPool pool(5);
118  Receiver receiver;
119  int kNumDependants = 10;
120  auto dependency_task = common::make_unique<Task>();
121  dependency_task->SetWorkItem([]() {});
122  auto dependency_handle = pool.Schedule(std::move(dependency_task));
123  for (int i = 0; i < kNumDependants; ++i) {
124  auto task = common::make_unique<Task>();
125  task->AddDependency(dependency_handle);
126  task->SetWorkItem([&receiver]() { receiver.Receive(1); });
127  pool.Schedule(std::move(task));
128  }
129  receiver.WaitForNumberSequence(std::vector<int>(kNumDependants, 1));
130  }
131 }
132 
133 TEST(ThreadPoolTest, RunWithMultipleDependencies) {
134  ThreadPool pool(2);
135  Receiver receiver;
136  auto task_1 = common::make_unique<Task>();
137  task_1->SetWorkItem([&receiver]() { receiver.Receive(1); });
138  auto task_2a = common::make_unique<Task>();
139  task_2a->SetWorkItem([&receiver]() { receiver.Receive(2); });
140  auto task_2b = common::make_unique<Task>();
141  task_2b->SetWorkItem([&receiver]() { receiver.Receive(2); });
142  auto task_3 = common::make_unique<Task>();
143  task_3->SetWorkItem([&receiver]() { receiver.Receive(3); });
144  /* -> task_2a \
145  * task_1 /-> task_2b --> task_3
146  */
147  auto weak_task_1 = pool.Schedule(std::move(task_1));
148  task_2a->AddDependency(weak_task_1);
149  auto weak_task_2a = pool.Schedule(std::move(task_2a));
150  task_3->AddDependency(weak_task_1);
151  task_3->AddDependency(weak_task_2a);
152  task_2b->AddDependency(weak_task_1);
153  auto weak_task_2b = pool.Schedule(std::move(task_2b));
154  task_3->AddDependency(weak_task_2b);
155  pool.Schedule(std::move(task_3));
156  receiver.WaitForNumberSequence({1, 2, 2, 3});
157 }
158 
159 TEST(ThreadPoolTest, RunWithFinishedDependency) {
160  ThreadPool pool(2);
161  Receiver receiver;
162  auto task_1 = common::make_unique<Task>();
163  task_1->SetWorkItem([&receiver]() { receiver.Receive(1); });
164  auto task_2 = common::make_unique<Task>();
165  task_2->SetWorkItem([&receiver]() { receiver.Receive(2); });
166  auto weak_task_1 = pool.Schedule(std::move(task_1));
167  task_2->AddDependency(weak_task_1);
168  receiver.WaitForNumberSequence({1});
169  pool.Schedule(std::move(task_2));
170  receiver.WaitForNumberSequence({1, 2});
171 }
172 
173 } // namespace
174 } // namespace common
175 } // namespace cartographer
#define GUARDED_BY(x)
Definition: mutex.h:40
#define REQUIRES(...)
Definition: mutex.h:44
Mutex::Locker MutexLocker
Definition: mutex.h:95
Mutex mutex_
TEST(TrajectoryConnectivityStateTest, UnknownTrajectory)


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58