blob: 11ee2abc9fec88f63a603aa13f88f9bb9b8c99bc [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 17:08:3311#include "rtc_base/thread.h"
12
kwibergbfefb032016-05-01 21:53:4613#include <memory>
14
Ali Tofigh4b681942022-08-23 10:57:1615#include "api/field_trials_view.h"
Danil Chapovalov912b3b82019-11-22 14:52:4016#include "api/task_queue/task_queue_factory.h"
17#include "api/task_queue/task_queue_test.h"
Danil Chapovalov4bcf8092022-07-06 17:42:3418#include "api/units/time_delta.h"
Steve Anton10542f22019-01-11 17:11:0019#include "rtc_base/async_udp_socket.h"
Mirko Bonadei481e3452021-07-30 11:57:2520#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3121#include "rtc_base/event.h"
Danil Chapovalov207f8532022-08-24 10:19:4622#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "rtc_base/gunit.h"
Mirko Bonadeie5f4c6b2021-01-15 09:41:0124#include "rtc_base/internal/default_socket_server.h"
Per Kc202f962023-12-14 12:09:0225#include "rtc_base/network/received_packet.h"
Steve Anton10542f22019-01-11 17:11:0026#include "rtc_base/null_socket_server.h"
27#include "rtc_base/physical_socket_server.h"
Danil Chapovalov16242932022-09-02 09:10:2428#include "rtc_base/ref_counted_object.h"
Steve Anton10542f22019-01-11 17:11:0029#include "rtc_base/socket_address.h"
Markus Handell4ab7dde2020-07-10 11:23:2530#include "rtc_base/synchronization/mutex.h"
Artem Titove41c4332018-07-25 13:04:2831#include "rtc_base/third_party/sigslot/sigslot.h"
Danil Chapovalov207f8532022-08-24 10:19:4632#include "test/gmock.h"
Sebastian Janssonda7267a2020-03-03 09:48:0533#include "test/testsupport/rtc_expect_death.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2634
35#if defined(WEBRTC_WIN)
36#include <comdef.h> // NOLINT
Markus Handell4ab7dde2020-07-10 11:23:2537
henrike@webrtc.orgf0488722014-05-13 18:00:2638#endif
39
Mirko Bonadeie10b1632018-12-11 17:43:4040namespace rtc {
41namespace {
henrike@webrtc.orgf0488722014-05-13 18:00:2642
Danil Chapovalov207f8532022-08-24 10:19:4643using ::testing::ElementsAre;
Danil Chapovalov4bcf8092022-07-06 17:42:3444using ::webrtc::TimeDelta;
Sebastian Jansson73387822020-01-16 10:15:3545
henrike@webrtc.orgf0488722014-05-13 18:00:2646// Generates a sequence of numbers (collaboratively).
47class TestGenerator {
48 public:
49 TestGenerator() : last(0), count(0) {}
50
51 int Next(int prev) {
52 int result = prev + last;
53 last = result;
54 count += 1;
55 return result;
56 }
57
58 int last;
59 int count;
60};
61
Danil Chapovalov1e6965a2022-09-05 09:27:5762// Receives messages and sends on a socket.
63class MessageClient : public TestGenerator {
64 public:
65 MessageClient(Thread* pth, Socket* socket) : socket_(socket) {}
henrike@webrtc.orgf0488722014-05-13 18:00:2666
Danil Chapovalov1e6965a2022-09-05 09:27:5767 ~MessageClient() { delete socket_; }
68
69 void OnValue(int value) {
70 int result = Next(value);
71 EXPECT_GE(socket_->Send(&result, sizeof(result)), 0);
72 }
73
74 private:
75 Socket* socket_;
henrike@webrtc.orgf0488722014-05-13 18:00:2676};
77
78// Receives on a socket and sends by posting messages.
79class SocketClient : public TestGenerator, public sigslot::has_slots<> {
80 public:
Niels Möllerd0b88792021-08-12 08:32:3081 SocketClient(Socket* socket,
Yves Gerey665174f2018-06-19 13:03:0582 const SocketAddress& addr,
83 Thread* post_thread,
Danil Chapovalov1e6965a2022-09-05 09:27:5784 MessageClient* phandler)
henrike@webrtc.orgf0488722014-05-13 18:00:2685 : socket_(AsyncUDPSocket::Create(socket, addr)),
86 post_thread_(post_thread),
87 post_handler_(phandler) {
Per Kc202f962023-12-14 12:09:0288 socket_->RegisterReceivedPacketCallback(
89 [&](rtc::AsyncPacketSocket* socket, const rtc::ReceivedPacket& packet) {
90 OnPacket(socket, packet);
91 });
henrike@webrtc.orgf0488722014-05-13 18:00:2692 }
93
Steve Anton9de3aac2017-10-24 17:08:2694 ~SocketClient() override { delete socket_; }
henrike@webrtc.orgf0488722014-05-13 18:00:2695
96 SocketAddress address() const { return socket_->GetLocalAddress(); }
97
Per Kc202f962023-12-14 12:09:0298 void OnPacket(AsyncPacketSocket* socket, const rtc::ReceivedPacket& packet) {
99 EXPECT_EQ(packet.payload().size(), sizeof(uint32_t));
100 uint32_t prev =
101 reinterpret_cast<const uint32_t*>(packet.payload().data())[0];
Peter Boström0c4e06b2015-10-07 10:23:21102 uint32_t result = Next(prev);
henrike@webrtc.orgf0488722014-05-13 18:00:26103
Danil Chapovalov1e6965a2022-09-05 09:27:57104 post_thread_->PostDelayedTask([post_handler_ = post_handler_,
105 result] { post_handler_->OnValue(result); },
106 TimeDelta::Millis(200));
henrike@webrtc.orgf0488722014-05-13 18:00:26107 }
108
109 private:
110 AsyncUDPSocket* socket_;
111 Thread* post_thread_;
Danil Chapovalov1e6965a2022-09-05 09:27:57112 MessageClient* post_handler_;
henrike@webrtc.orgf0488722014-05-13 18:00:26113};
114
deadbeefaea92932017-05-23 19:55:03115class CustomThread : public rtc::Thread {
henrike@webrtc.orgf0488722014-05-13 18:00:26116 public:
tommie7251592017-07-14 21:44:46117 CustomThread()
118 : Thread(std::unique_ptr<SocketServer>(new rtc::NullSocketServer())) {}
Steve Anton9de3aac2017-10-24 17:08:26119 ~CustomThread() override { Stop(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26120 bool Start() { return false; }
jiayl@webrtc.orgba737cb2014-09-18 16:45:21121
Yves Gerey665174f2018-06-19 13:03:05122 bool WrapCurrent() { return Thread::WrapCurrent(); }
123 void UnwrapCurrent() { Thread::UnwrapCurrent(); }
henrike@webrtc.orgf0488722014-05-13 18:00:26124};
125
henrike@webrtc.orgf0488722014-05-13 18:00:26126// A thread that does nothing when it runs and signals an event
127// when it is destroyed.
128class SignalWhenDestroyedThread : public Thread {
129 public:
130 SignalWhenDestroyedThread(Event* event)
tommie7251592017-07-14 21:44:46131 : Thread(std::unique_ptr<SocketServer>(new NullSocketServer())),
132 event_(event) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26133
Steve Anton9de3aac2017-10-24 17:08:26134 ~SignalWhenDestroyedThread() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26135 Stop();
136 event_->Set();
137 }
138
Steve Anton9de3aac2017-10-24 17:08:26139 void Run() override {
henrike@webrtc.orgf0488722014-05-13 18:00:26140 // Do nothing.
141 }
142
143 private:
144 Event* event_;
145};
146
henrike@webrtc.orgf0488722014-05-13 18:00:26147// See: https://code.google.com/p/webrtc/issues/detail?id=2409
148TEST(ThreadTest, DISABLED_Main) {
Danil Chapovalov1e6965a2022-09-05 09:27:57149 rtc::AutoThread main_thread;
henrike@webrtc.orgf0488722014-05-13 18:00:26150 const SocketAddress addr("127.0.0.1", 0);
151
152 // Create the messaging client on its own thread.
tommie7251592017-07-14 21:44:46153 auto th1 = Thread::CreateWithSocketServer();
Niels Möllerd0b88792021-08-12 08:32:30154 Socket* socket = th1->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
tommie7251592017-07-14 21:44:46155 MessageClient msg_client(th1.get(), socket);
henrike@webrtc.orgf0488722014-05-13 18:00:26156
157 // Create the socket client on its own thread.
tommie7251592017-07-14 21:44:46158 auto th2 = Thread::CreateWithSocketServer();
Niels Möllerd0b88792021-08-12 08:32:30159 Socket* asocket =
160 th2->socketserver()->CreateSocket(addr.family(), SOCK_DGRAM);
tommie7251592017-07-14 21:44:46161 SocketClient sock_client(asocket, addr, th1.get(), &msg_client);
henrike@webrtc.orgf0488722014-05-13 18:00:26162
163 socket->Connect(sock_client.address());
164
tommie7251592017-07-14 21:44:46165 th1->Start();
166 th2->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26167
168 // Get the messages started.
Danil Chapovalov1e6965a2022-09-05 09:27:57169 th1->PostDelayedTask([&msg_client] { msg_client.OnValue(1); },
170 TimeDelta::Millis(100));
henrike@webrtc.orgf0488722014-05-13 18:00:26171
172 // Give the clients a little while to run.
173 // Messages will be processed at 100, 300, 500, 700, 900.
174 Thread* th_main = Thread::Current();
175 th_main->ProcessMessages(1000);
176
177 // Stop the sending client. Give the receiver a bit longer to run, in case
178 // it is running on a machine that is under load (e.g. the build machine).
tommie7251592017-07-14 21:44:46179 th1->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26180 th_main->ProcessMessages(200);
tommie7251592017-07-14 21:44:46181 th2->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26182
183 // Make sure the results were correct
184 EXPECT_EQ(5, msg_client.count);
185 EXPECT_EQ(34, msg_client.last);
186 EXPECT_EQ(5, sock_client.count);
187 EXPECT_EQ(55, sock_client.last);
188}
189
Tommife041642021-04-07 08:08:28190TEST(ThreadTest, CountBlockingCalls) {
Niels Möller83830f32022-05-20 07:12:57191 rtc::AutoThread current;
192
Tommife041642021-04-07 08:08:28193 // When the test runs, this will print out:
194 // (thread_unittest.cc:262): Blocking TestBody: total=2 (actual=1, could=1)
195 RTC_LOG_THREAD_BLOCK_COUNT();
196#if RTC_DCHECK_IS_ON
Tommife041642021-04-07 08:08:28197 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
198 [&](uint32_t actual_block, uint32_t could_block) {
199 EXPECT_EQ(1u, actual_block);
200 EXPECT_EQ(1u, could_block);
201 });
202
203 EXPECT_EQ(0u, blocked_calls.GetBlockingCallCount());
204 EXPECT_EQ(0u, blocked_calls.GetCouldBeBlockingCallCount());
205 EXPECT_EQ(0u, blocked_calls.GetTotalBlockedCallCount());
206
207 // Test invoking on the current thread. This should not count as an 'actual'
208 // invoke, but should still count as an invoke that could block since we
Danil Chapovalov7c323ad2022-09-08 11:13:53209 // that the call to `BlockingCall` serves a purpose in some configurations
210 // (and should not be used a general way to call methods on the same thread).
211 current.BlockingCall([]() {});
Tommife041642021-04-07 08:08:28212 EXPECT_EQ(0u, blocked_calls.GetBlockingCallCount());
213 EXPECT_EQ(1u, blocked_calls.GetCouldBeBlockingCallCount());
214 EXPECT_EQ(1u, blocked_calls.GetTotalBlockedCallCount());
215
216 // Create a new thread to invoke on.
217 auto thread = Thread::CreateWithSocketServer();
218 thread->Start();
Danil Chapovalov7c323ad2022-09-08 11:13:53219 EXPECT_EQ(42, thread->BlockingCall([]() { return 42; }));
Tommife041642021-04-07 08:08:28220 EXPECT_EQ(1u, blocked_calls.GetBlockingCallCount());
221 EXPECT_EQ(1u, blocked_calls.GetCouldBeBlockingCallCount());
222 EXPECT_EQ(2u, blocked_calls.GetTotalBlockedCallCount());
223 thread->Stop();
224 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
225#else
226 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
227 RTC_LOG(LS_INFO) << "Test not active in this config";
228#endif
229}
230
Tomas Gunnarsson89f3dd52021-04-14 10:54:10231#if RTC_DCHECK_IS_ON
232TEST(ThreadTest, CountBlockingCallsOneCallback) {
Niels Möller83830f32022-05-20 07:12:57233 rtc::AutoThread current;
Tomas Gunnarsson89f3dd52021-04-14 10:54:10234 bool was_called_back = false;
235 {
236 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
237 [&](uint32_t actual_block, uint32_t could_block) {
238 was_called_back = true;
239 });
Danil Chapovalov7c323ad2022-09-08 11:13:53240 current.BlockingCall([]() {});
Tomas Gunnarsson89f3dd52021-04-14 10:54:10241 }
242 EXPECT_TRUE(was_called_back);
243}
244
245TEST(ThreadTest, CountBlockingCallsSkipCallback) {
Niels Möller83830f32022-05-20 07:12:57246 rtc::AutoThread current;
Tomas Gunnarsson89f3dd52021-04-14 10:54:10247 bool was_called_back = false;
248 {
249 rtc::Thread::ScopedCountBlockingCalls blocked_calls(
250 [&](uint32_t actual_block, uint32_t could_block) {
251 was_called_back = true;
252 });
253 // Changed `blocked_calls` to not issue the callback if there are 1 or
254 // fewer blocking calls (i.e. we set the minimum required number to 2).
255 blocked_calls.set_minimum_call_count_for_callback(2);
Danil Chapovalov7c323ad2022-09-08 11:13:53256 current.BlockingCall([]() {});
Tomas Gunnarsson89f3dd52021-04-14 10:54:10257 }
258 // We should not have gotten a call back.
259 EXPECT_FALSE(was_called_back);
260}
261#endif
262
henrike@webrtc.orgf0488722014-05-13 18:00:26263// Test that setting thread names doesn't cause a malfunction.
264// There's no easy way to verify the name was set properly at this time.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15265TEST(ThreadTest, Names) {
henrike@webrtc.orgf0488722014-05-13 18:00:26266 // Default name
tommie7251592017-07-14 21:44:46267 auto thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26268 EXPECT_TRUE(thread->Start());
269 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26270 // Name with no object parameter
tommie7251592017-07-14 21:44:46271 thread = Thread::CreateWithSocketServer();
deadbeef37f5ecf2017-02-27 22:06:41272 EXPECT_TRUE(thread->SetName("No object", nullptr));
henrike@webrtc.orgf0488722014-05-13 18:00:26273 EXPECT_TRUE(thread->Start());
274 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26275 // Really long name
tommie7251592017-07-14 21:44:46276 thread = Thread::CreateWithSocketServer();
henrike@webrtc.orgf0488722014-05-13 18:00:26277 EXPECT_TRUE(thread->SetName("Abcdefghijklmnopqrstuvwxyz1234567890", this));
278 EXPECT_TRUE(thread->Start());
279 thread->Stop();
henrike@webrtc.orgf0488722014-05-13 18:00:26280}
281
henrike@webrtc.orge30dab72014-10-09 15:41:40282TEST(ThreadTest, Wrap) {
283 Thread* current_thread = Thread::Current();
Niels Möller5a8f8602019-06-12 09:30:59284 ThreadManager::Instance()->SetCurrentThread(nullptr);
285
286 {
287 CustomThread cthread;
288 EXPECT_TRUE(cthread.WrapCurrent());
289 EXPECT_EQ(&cthread, Thread::Current());
290 EXPECT_TRUE(cthread.RunningForTest());
291 EXPECT_FALSE(cthread.IsOwned());
292 cthread.UnwrapCurrent();
293 EXPECT_FALSE(cthread.RunningForTest());
294 }
295 ThreadManager::Instance()->SetCurrentThread(current_thread);
henrike@webrtc.orgf0488722014-05-13 18:00:26296}
297
Mirko Bonadei481e3452021-07-30 11:57:25298#if (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
Artem Titovdfc5f0d2020-07-03 10:09:26299TEST(ThreadTest, InvokeToThreadAllowedReturnsTrueWithoutPolicies) {
Niels Möller83830f32022-05-20 07:12:57300 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 10:09:26301 // Create and start the thread.
302 auto thread1 = Thread::CreateWithSocketServer();
303 auto thread2 = Thread::CreateWithSocketServer();
304
Danil Chapovalov4bcf8092022-07-06 17:42:34305 thread1->PostTask(
306 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 07:12:57307 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 10:09:26308}
309
310TEST(ThreadTest, InvokeAllowedWhenThreadsAdded) {
Niels Möller83830f32022-05-20 07:12:57311 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 10:09:26312 // Create and start the thread.
313 auto thread1 = Thread::CreateWithSocketServer();
314 auto thread2 = Thread::CreateWithSocketServer();
315 auto thread3 = Thread::CreateWithSocketServer();
316 auto thread4 = Thread::CreateWithSocketServer();
317
318 thread1->AllowInvokesToThread(thread2.get());
319 thread1->AllowInvokesToThread(thread3.get());
320
Danil Chapovalov4bcf8092022-07-06 17:42:34321 thread1->PostTask([&]() {
Artem Titovdfc5f0d2020-07-03 10:09:26322 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get()));
323 EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread3.get()));
324 EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread4.get()));
Danil Chapovalov4bcf8092022-07-06 17:42:34325 });
Niels Möller83830f32022-05-20 07:12:57326 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 10:09:26327}
328
329TEST(ThreadTest, InvokesDisallowedWhenDisallowAllInvokes) {
Niels Möller83830f32022-05-20 07:12:57330 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 10:09:26331 // Create and start the thread.
332 auto thread1 = Thread::CreateWithSocketServer();
333 auto thread2 = Thread::CreateWithSocketServer();
334
335 thread1->DisallowAllInvokes();
336
Danil Chapovalov4bcf8092022-07-06 17:42:34337 thread1->PostTask(
338 [&]() { EXPECT_FALSE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 07:12:57339 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 10:09:26340}
Mirko Bonadei481e3452021-07-30 11:57:25341#endif // (!defined(NDEBUG) || RTC_DCHECK_IS_ON)
Artem Titovdfc5f0d2020-07-03 10:09:26342
343TEST(ThreadTest, InvokesAllowedByDefault) {
Niels Möller83830f32022-05-20 07:12:57344 rtc::AutoThread main_thread;
Artem Titovdfc5f0d2020-07-03 10:09:26345 // Create and start the thread.
346 auto thread1 = Thread::CreateWithSocketServer();
347 auto thread2 = Thread::CreateWithSocketServer();
348
Danil Chapovalov4bcf8092022-07-06 17:42:34349 thread1->PostTask(
350 [&]() { EXPECT_TRUE(thread1->IsInvokeToThreadAllowed(thread2.get())); });
Niels Möller83830f32022-05-20 07:12:57351 main_thread.ProcessMessages(100);
Artem Titovdfc5f0d2020-07-03 10:09:26352}
353
Danil Chapovalov7c323ad2022-09-08 11:13:53354TEST(ThreadTest, BlockingCall) {
henrike@webrtc.orgf0488722014-05-13 18:00:26355 // Create and start the thread.
tommie7251592017-07-14 21:44:46356 auto thread = Thread::CreateWithSocketServer();
357 thread->Start();
henrike@webrtc.orgf0488722014-05-13 18:00:26358 // Try calling functors.
Danil Chapovalov7c323ad2022-09-08 11:13:53359 EXPECT_EQ(42, thread->BlockingCall([] { return 42; }));
360 bool called = false;
361 thread->BlockingCall([&] { called = true; });
362 EXPECT_TRUE(called);
363
henrike@webrtc.orgf0488722014-05-13 18:00:26364 // Try calling bare functions.
365 struct LocalFuncs {
366 static int Func1() { return 999; }
367 static void Func2() {}
368 };
Danil Chapovalov7c323ad2022-09-08 11:13:53369 EXPECT_EQ(999, thread->BlockingCall(&LocalFuncs::Func1));
370 thread->BlockingCall(&LocalFuncs::Func2);
henrike@webrtc.orgf0488722014-05-13 18:00:26371}
372
jiayl@webrtc.org3987b6d2014-09-24 17:14:05373// Verifies that two threads calling Invoke on each other at the same time does
Sebastian Janssonda7267a2020-03-03 09:48:05374// not deadlock but crash.
375#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
376TEST(ThreadTest, TwoThreadsInvokeDeathTest) {
Mirko Bonadei386b5c32021-07-28 06:55:52377 GTEST_FLAG_SET(death_test_style, "threadsafe");
jiayl@webrtc.org3987b6d2014-09-24 17:14:05378 AutoThread thread;
Sebastian Janssonda7267a2020-03-03 09:48:05379 Thread* main_thread = Thread::Current();
tommie7251592017-07-14 21:44:46380 auto other_thread = Thread::CreateWithSocketServer();
381 other_thread->Start();
Danil Chapovalov7c323ad2022-09-08 11:13:53382 other_thread->BlockingCall([main_thread] {
383 RTC_EXPECT_DEATH(main_thread->BlockingCall([] {}), "loop");
Sebastian Janssonda7267a2020-03-03 09:48:05384 });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05385}
386
Sebastian Janssonda7267a2020-03-03 09:48:05387TEST(ThreadTest, ThreeThreadsInvokeDeathTest) {
Mirko Bonadei386b5c32021-07-28 06:55:52388 GTEST_FLAG_SET(death_test_style, "threadsafe");
Sebastian Janssonda7267a2020-03-03 09:48:05389 AutoThread thread;
390 Thread* first = Thread::Current();
391
392 auto second = Thread::Create();
393 second->Start();
394 auto third = Thread::Create();
395 third->Start();
396
Danil Chapovalov7c323ad2022-09-08 11:13:53397 second->BlockingCall([&] {
398 third->BlockingCall(
399 [&] { RTC_EXPECT_DEATH(first->BlockingCall([] {}), "loop"); });
Sebastian Janssonda7267a2020-03-03 09:48:05400 });
401}
402
403#endif
404
jiayl@webrtc.org3987b6d2014-09-24 17:14:05405// Verifies that if thread A invokes a call on thread B and thread C is trying
406// to invoke A at the same time, thread A does not handle C's invoke while
407// invoking B.
Danil Chapovalov7c323ad2022-09-08 11:13:53408TEST(ThreadTest, ThreeThreadsBlockingCall) {
jiayl@webrtc.org3987b6d2014-09-24 17:14:05409 AutoThread thread;
410 Thread* thread_a = Thread::Current();
tommie7251592017-07-14 21:44:46411 auto thread_b = Thread::CreateWithSocketServer();
412 auto thread_c = Thread::CreateWithSocketServer();
413 thread_b->Start();
414 thread_c->Start();
jiayl@webrtc.org3987b6d2014-09-24 17:14:05415
pbos@webrtc.orge93cbd12014-10-15 14:54:56416 class LockedBool {
417 public:
418 explicit LockedBool(bool value) : value_(value) {}
419
420 void Set(bool value) {
Markus Handell4ab7dde2020-07-10 11:23:25421 webrtc::MutexLock lock(&mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56422 value_ = value;
423 }
424
425 bool Get() {
Markus Handell4ab7dde2020-07-10 11:23:25426 webrtc::MutexLock lock(&mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56427 return value_;
428 }
429
430 private:
Markus Handell4ab7dde2020-07-10 11:23:25431 webrtc::Mutex mutex_;
432 bool value_ RTC_GUARDED_BY(mutex_);
pbos@webrtc.orge93cbd12014-10-15 14:54:56433 };
434
jiayl@webrtc.org3987b6d2014-09-24 17:14:05435 struct LocalFuncs {
pbos@webrtc.orge93cbd12014-10-15 14:54:56436 static void Set(LockedBool* out) { out->Set(true); }
437 static void InvokeSet(Thread* thread, LockedBool* out) {
Danil Chapovalov7c323ad2022-09-08 11:13:53438 thread->BlockingCall([out] { Set(out); });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05439 }
440
Artem Titov96e3b992021-07-26 14:03:14441 // Set `out` true and call InvokeSet on `thread`.
pbos@webrtc.orge93cbd12014-10-15 14:54:56442 static void SetAndInvokeSet(LockedBool* out,
443 Thread* thread,
444 LockedBool* out_inner) {
445 out->Set(true);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05446 InvokeSet(thread, out_inner);
447 }
448
Artem Titov96e3b992021-07-26 14:03:14449 // Asynchronously invoke SetAndInvokeSet on `thread1` and wait until
450 // `thread1` starts the call.
Danil Chapovalov16242932022-09-02 09:10:24451 static void AsyncInvokeSetAndWait(Thread* thread1,
deadbeef162cb532017-02-24 01:10:07452 Thread* thread2,
453 LockedBool* out) {
pbos@webrtc.orge93cbd12014-10-15 14:54:56454 LockedBool async_invoked(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05455
Danil Chapovalov16242932022-09-02 09:10:24456 thread1->PostTask([&async_invoked, thread2, out] {
457 SetAndInvokeSet(&async_invoked, thread2, out);
458 });
jiayl@webrtc.org3987b6d2014-09-24 17:14:05459
pbos@webrtc.orge93cbd12014-10-15 14:54:56460 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05461 }
462 };
463
pbos@webrtc.orge93cbd12014-10-15 14:54:56464 LockedBool thread_a_called(false);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05465
466 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
467 // Thread B returns when C receives the call and C should be blocked until A
468 // starts to process messages.
Niels Möller1a29a5d2021-01-18 10:35:23469 Thread* thread_c_ptr = thread_c.get();
Danil Chapovalov7c323ad2022-09-08 11:13:53470 thread_b->BlockingCall([thread_c_ptr, thread_a, &thread_a_called] {
Danil Chapovalov16242932022-09-02 09:10:24471 LocalFuncs::AsyncInvokeSetAndWait(thread_c_ptr, thread_a, &thread_a_called);
472 });
pbos@webrtc.orge93cbd12014-10-15 14:54:56473 EXPECT_FALSE(thread_a_called.Get());
jiayl@webrtc.org3987b6d2014-09-24 17:14:05474
pbos@webrtc.orge93cbd12014-10-15 14:54:56475 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
jiayl@webrtc.org3987b6d2014-09-24 17:14:05476}
477
Danil Chapovalov207f8532022-08-24 10:19:46478static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(
479 FakeClock& clock,
480 Thread& q) {
481 std::vector<int> run_order;
482
483 Event done;
Sebastian Jansson73387822020-01-16 10:15:35484 int64_t now = TimeMillis();
Danil Chapovalov207f8532022-08-24 10:19:46485 q.PostDelayedTask([&] { run_order.push_back(3); }, TimeDelta::Millis(3));
486 q.PostDelayedTask([&] { run_order.push_back(0); }, TimeDelta::Millis(1));
487 q.PostDelayedTask([&] { run_order.push_back(1); }, TimeDelta::Millis(2));
488 q.PostDelayedTask([&] { run_order.push_back(4); }, TimeDelta::Millis(3));
489 q.PostDelayedTask([&] { run_order.push_back(2); }, TimeDelta::Millis(2));
490 q.PostDelayedTask([&] { done.Set(); }, TimeDelta::Millis(4));
491 // Validate time was frozen while tasks were posted.
492 RTC_DCHECK_EQ(TimeMillis(), now);
Sebastian Jansson73387822020-01-16 10:15:35493
Danil Chapovalov207f8532022-08-24 10:19:46494 // Change time to make all tasks ready to run and wait for them.
495 clock.AdvanceTime(TimeDelta::Millis(4));
496 ASSERT_TRUE(done.Wait(TimeDelta::Seconds(1)));
Sebastian Jansson73387822020-01-16 10:15:35497
Danil Chapovalov207f8532022-08-24 10:19:46498 EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
Sebastian Jansson73387822020-01-16 10:15:35499}
500
Danil Chapovalov71cf2d02022-08-26 09:49:14501TEST(ThreadTest, DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) {
Danil Chapovalov207f8532022-08-24 10:19:46502 ScopedBaseFakeClock clock;
Mirko Bonadeie5f4c6b2021-01-15 09:41:01503 Thread q(CreateDefaultSocketServer(), true);
Danil Chapovalov207f8532022-08-24 10:19:46504 q.Start();
505 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q);
Sebastian Jansson73387822020-01-16 10:15:35506
507 NullSocketServer nullss;
508 Thread q_nullss(&nullss, true);
Danil Chapovalov207f8532022-08-24 10:19:46509 q_nullss.Start();
510 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(clock, q_nullss);
Sebastian Jansson73387822020-01-16 10:15:35511}
512
Sebastian Jansson73387822020-01-16 10:15:35513// Ensure that ProcessAllMessageQueues does its essential function; process
514// all messages (both delayed and non delayed) up until the current time, on
515// all registered message queues.
516TEST(ThreadManager, ProcessAllMessageQueues) {
Niels Möller83830f32022-05-20 07:12:57517 rtc::AutoThread main_thread;
Sebastian Jansson73387822020-01-16 10:15:35518 Event entered_process_all_message_queues(true, false);
519 auto a = Thread::CreateWithSocketServer();
520 auto b = Thread::CreateWithSocketServer();
521 a->Start();
522 b->Start();
523
Niels Möller7a669002022-06-27 07:47:02524 std::atomic<int> messages_processed(0);
Sebastian Jansson73387822020-01-16 10:15:35525 auto incrementer = [&messages_processed,
526 &entered_process_all_message_queues] {
527 // Wait for event as a means to ensure Increment doesn't occur outside
528 // of ProcessAllMessageQueues. The event is set by a message posted to
529 // the main thread, which is guaranteed to be handled inside
530 // ProcessAllMessageQueues.
531 entered_process_all_message_queues.Wait(Event::kForever);
Niels Möller7a669002022-06-27 07:47:02532 messages_processed.fetch_add(1);
Sebastian Jansson73387822020-01-16 10:15:35533 };
534 auto event_signaler = [&entered_process_all_message_queues] {
535 entered_process_all_message_queues.Set();
536 };
537
538 // Post messages (both delayed and non delayed) to both threads.
Danil Chapovalov4bcf8092022-07-06 17:42:34539 a->PostTask(incrementer);
540 b->PostTask(incrementer);
541 a->PostDelayedTask(incrementer, TimeDelta::Zero());
542 b->PostDelayedTask(incrementer, TimeDelta::Zero());
543 main_thread.PostTask(event_signaler);
Sebastian Jansson73387822020-01-16 10:15:35544
545 ThreadManager::ProcessAllMessageQueuesForTesting();
Niels Möller7a669002022-06-27 07:47:02546 EXPECT_EQ(4, messages_processed.load(std::memory_order_acquire));
Sebastian Jansson73387822020-01-16 10:15:35547}
548
549// Test that ProcessAllMessageQueues doesn't hang if a thread is quitting.
550TEST(ThreadManager, ProcessAllMessageQueuesWithQuittingThread) {
551 auto t = Thread::CreateWithSocketServer();
552 t->Start();
553 t->Quit();
554 ThreadManager::ProcessAllMessageQueuesForTesting();
555}
556
Henrik Boströmba4dcc32019-02-28 08:34:06557void WaitAndSetEvent(Event* wait_event, Event* set_event) {
558 wait_event->Wait(Event::kForever);
559 set_event->Set();
560}
561
562// A functor that keeps track of the number of copies and moves.
563class LifeCycleFunctor {
564 public:
565 struct Stats {
566 size_t copy_count = 0;
567 size_t move_count = 0;
568 };
569
570 LifeCycleFunctor(Stats* stats, Event* event) : stats_(stats), event_(event) {}
571 LifeCycleFunctor(const LifeCycleFunctor& other) { *this = other; }
572 LifeCycleFunctor(LifeCycleFunctor&& other) { *this = std::move(other); }
573
574 LifeCycleFunctor& operator=(const LifeCycleFunctor& other) {
575 stats_ = other.stats_;
576 event_ = other.event_;
577 ++stats_->copy_count;
578 return *this;
579 }
580
581 LifeCycleFunctor& operator=(LifeCycleFunctor&& other) {
582 stats_ = other.stats_;
583 event_ = other.event_;
584 ++stats_->move_count;
585 return *this;
586 }
587
588 void operator()() { event_->Set(); }
589
590 private:
591 Stats* stats_;
592 Event* event_;
593};
594
595// A functor that verifies the thread it was destroyed on.
596class DestructionFunctor {
597 public:
598 DestructionFunctor(Thread* thread, bool* thread_was_current, Event* event)
599 : thread_(thread),
600 thread_was_current_(thread_was_current),
601 event_(event) {}
602 ~DestructionFunctor() {
603 // Only signal the event if this was the functor that was invoked to avoid
604 // the event being signaled due to the destruction of temporary/moved
605 // versions of this object.
606 if (was_invoked_) {
607 *thread_was_current_ = thread_->IsCurrent();
608 event_->Set();
609 }
610 }
611
612 void operator()() { was_invoked_ = true; }
613
614 private:
615 Thread* thread_;
616 bool* thread_was_current_;
617 Event* event_;
618 bool was_invoked_ = false;
619};
620
Henrik Boströmba4dcc32019-02-28 08:34:06621TEST(ThreadPostTaskTest, InvokesWithLambda) {
622 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
623 background_thread->Start();
624
625 Event event;
Henrik Boström595f6882022-01-24 08:57:03626 background_thread->PostTask([&event] { event.Set(); });
Henrik Boströmba4dcc32019-02-28 08:34:06627 event.Wait(Event::kForever);
628}
629
630TEST(ThreadPostTaskTest, InvokesWithCopiedFunctor) {
631 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
632 background_thread->Start();
633
634 LifeCycleFunctor::Stats stats;
635 Event event;
636 LifeCycleFunctor functor(&stats, &event);
Henrik Boström595f6882022-01-24 08:57:03637 background_thread->PostTask(functor);
Henrik Boströmba4dcc32019-02-28 08:34:06638 event.Wait(Event::kForever);
639
640 EXPECT_EQ(1u, stats.copy_count);
641 EXPECT_EQ(0u, stats.move_count);
642}
643
644TEST(ThreadPostTaskTest, InvokesWithMovedFunctor) {
645 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
646 background_thread->Start();
647
648 LifeCycleFunctor::Stats stats;
649 Event event;
650 LifeCycleFunctor functor(&stats, &event);
Henrik Boström595f6882022-01-24 08:57:03651 background_thread->PostTask(std::move(functor));
Henrik Boströmba4dcc32019-02-28 08:34:06652 event.Wait(Event::kForever);
653
654 EXPECT_EQ(0u, stats.copy_count);
655 EXPECT_EQ(1u, stats.move_count);
656}
657
658TEST(ThreadPostTaskTest, InvokesWithReferencedFunctorShouldCopy) {
659 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
660 background_thread->Start();
661
662 LifeCycleFunctor::Stats stats;
663 Event event;
664 LifeCycleFunctor functor(&stats, &event);
665 LifeCycleFunctor& functor_ref = functor;
Henrik Boström595f6882022-01-24 08:57:03666 background_thread->PostTask(functor_ref);
Henrik Boströmba4dcc32019-02-28 08:34:06667 event.Wait(Event::kForever);
668
669 EXPECT_EQ(1u, stats.copy_count);
670 EXPECT_EQ(0u, stats.move_count);
671}
672
673TEST(ThreadPostTaskTest, InvokesWithCopiedFunctorDestroyedOnTargetThread) {
674 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
675 background_thread->Start();
676
677 Event event;
678 bool was_invoked_on_background_thread = false;
679 DestructionFunctor functor(background_thread.get(),
680 &was_invoked_on_background_thread, &event);
Henrik Boström595f6882022-01-24 08:57:03681 background_thread->PostTask(functor);
Henrik Boströmba4dcc32019-02-28 08:34:06682 event.Wait(Event::kForever);
683
684 EXPECT_TRUE(was_invoked_on_background_thread);
685}
686
687TEST(ThreadPostTaskTest, InvokesWithMovedFunctorDestroyedOnTargetThread) {
688 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
689 background_thread->Start();
690
691 Event event;
692 bool was_invoked_on_background_thread = false;
693 DestructionFunctor functor(background_thread.get(),
694 &was_invoked_on_background_thread, &event);
Henrik Boström595f6882022-01-24 08:57:03695 background_thread->PostTask(std::move(functor));
Henrik Boströmba4dcc32019-02-28 08:34:06696 event.Wait(Event::kForever);
697
698 EXPECT_TRUE(was_invoked_on_background_thread);
699}
700
701TEST(ThreadPostTaskTest,
702 InvokesWithReferencedFunctorShouldCopyAndDestroyedOnTargetThread) {
703 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
704 background_thread->Start();
705
706 Event event;
707 bool was_invoked_on_background_thread = false;
708 DestructionFunctor functor(background_thread.get(),
709 &was_invoked_on_background_thread, &event);
710 DestructionFunctor& functor_ref = functor;
Henrik Boström595f6882022-01-24 08:57:03711 background_thread->PostTask(functor_ref);
Henrik Boströmba4dcc32019-02-28 08:34:06712 event.Wait(Event::kForever);
713
714 EXPECT_TRUE(was_invoked_on_background_thread);
715}
716
717TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
718 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
719 background_thread->Start();
720
721 Event event;
722 bool was_invoked_on_background_thread = false;
Niels Möller1a29a5d2021-01-18 10:35:23723 Thread* background_thread_ptr = background_thread.get();
Henrik Boström595f6882022-01-24 08:57:03724 background_thread->PostTask(
Niels Möller1a29a5d2021-01-18 10:35:23725 [background_thread_ptr, &was_invoked_on_background_thread, &event] {
726 was_invoked_on_background_thread = background_thread_ptr->IsCurrent();
727 event.Set();
728 });
Henrik Boströmba4dcc32019-02-28 08:34:06729 event.Wait(Event::kForever);
730
731 EXPECT_TRUE(was_invoked_on_background_thread);
732}
733
734TEST(ThreadPostTaskTest, InvokesAsynchronously) {
735 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
736 background_thread->Start();
737
738 // The first event ensures that SendSingleMessage() is not blocking this
739 // thread. The second event ensures that the message is processed.
740 Event event_set_by_test_thread;
741 Event event_set_by_background_thread;
Jared Siskin802e8e52023-04-20 00:35:28742 background_thread->PostTask([&event_set_by_test_thread,
743 &event_set_by_background_thread] {
744 WaitAndSetEvent(&event_set_by_test_thread, &event_set_by_background_thread);
745 });
Henrik Boströmba4dcc32019-02-28 08:34:06746 event_set_by_test_thread.Set();
747 event_set_by_background_thread.Wait(Event::kForever);
748}
749
750TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
751 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
752 background_thread->Start();
753
754 Event first;
755 Event second;
756 Event third;
757 Event fourth;
758
Henrik Boström595f6882022-01-24 08:57:03759 background_thread->PostTask(
760 [&first, &second] { WaitAndSetEvent(&first, &second); });
761 background_thread->PostTask(
762 [&second, &third] { WaitAndSetEvent(&second, &third); });
763 background_thread->PostTask(
764 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); });
Henrik Boströmba4dcc32019-02-28 08:34:06765
766 // All tasks have been posted before the first one is unblocked.
767 first.Set();
768 // Only if the chain is invoked in posted order will the last event be set.
769 fourth.Wait(Event::kForever);
770}
771
Steve Antonbcc1a762019-12-11 19:21:53772TEST(ThreadPostDelayedTaskTest, InvokesAsynchronously) {
773 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
774 background_thread->Start();
775
776 // The first event ensures that SendSingleMessage() is not blocking this
777 // thread. The second event ensures that the message is processed.
778 Event event_set_by_test_thread;
779 Event event_set_by_background_thread;
Henrik Boström595f6882022-01-24 08:57:03780 background_thread->PostDelayedTask(
Niels Möller1a29a5d2021-01-18 10:35:23781 [&event_set_by_test_thread, &event_set_by_background_thread] {
782 WaitAndSetEvent(&event_set_by_test_thread,
783 &event_set_by_background_thread);
784 },
Danil Chapovalov4bcf8092022-07-06 17:42:34785 TimeDelta::Millis(10));
Steve Antonbcc1a762019-12-11 19:21:53786 event_set_by_test_thread.Set();
787 event_set_by_background_thread.Wait(Event::kForever);
788}
789
790TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
Steve Anton094396f2019-12-16 08:56:02791 ScopedFakeClock clock;
Steve Antonbcc1a762019-12-11 19:21:53792 std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
793 background_thread->Start();
794
795 Event first;
796 Event second;
797 Event third;
798 Event fourth;
799
Henrik Boström595f6882022-01-24 08:57:03800 background_thread->PostDelayedTask(
801 [&third, &fourth] { WaitAndSetEvent(&third, &fourth); },
Danil Chapovalov4bcf8092022-07-06 17:42:34802 TimeDelta::Millis(11));
Henrik Boström595f6882022-01-24 08:57:03803 background_thread->PostDelayedTask(
804 [&first, &second] { WaitAndSetEvent(&first, &second); },
Danil Chapovalov4bcf8092022-07-06 17:42:34805 TimeDelta::Millis(9));
Henrik Boström595f6882022-01-24 08:57:03806 background_thread->PostDelayedTask(
807 [&second, &third] { WaitAndSetEvent(&second, &third); },
Danil Chapovalov4bcf8092022-07-06 17:42:34808 TimeDelta::Millis(10));
Steve Antonbcc1a762019-12-11 19:21:53809
810 // All tasks have been posted before the first one is unblocked.
811 first.Set();
Steve Anton094396f2019-12-16 08:56:02812 // Only if the chain is invoked in delay order will the last event be set.
Danil Chapovalov4bcf8092022-07-06 17:42:34813 clock.AdvanceTime(TimeDelta::Millis(11));
Markus Handell2cfc1af2022-08-19 08:16:48814 EXPECT_TRUE(fourth.Wait(TimeDelta::Zero()));
Steve Antonbcc1a762019-12-11 19:21:53815}
816
Tommi6866dc72020-05-15 08:11:56817TEST(ThreadPostDelayedTaskTest, IsCurrentTaskQueue) {
818 auto current_tq = webrtc::TaskQueueBase::Current();
819 {
820 std::unique_ptr<rtc::Thread> thread(rtc::Thread::Create());
821 thread->WrapCurrent();
822 EXPECT_EQ(webrtc::TaskQueueBase::Current(),
823 static_cast<webrtc::TaskQueueBase*>(thread.get()));
824 thread->UnwrapCurrent();
825 }
826 EXPECT_EQ(webrtc::TaskQueueBase::Current(), current_tq);
827}
828
Danil Chapovalov912b3b82019-11-22 14:52:40829class ThreadFactory : public webrtc::TaskQueueFactory {
830 public:
831 std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
832 CreateTaskQueue(absl::string_view /* name */,
833 Priority /*priority*/) const override {
834 std::unique_ptr<Thread> thread = Thread::Create();
835 thread->Start();
836 return std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>(
837 thread.release());
838 }
839};
840
Ali Tofigh4b681942022-08-23 10:57:16841std::unique_ptr<webrtc::TaskQueueFactory> CreateDefaultThreadFactory(
842 const webrtc::FieldTrialsView*) {
843 return std::make_unique<ThreadFactory>();
844}
845
Danil Chapovalov912b3b82019-11-22 14:52:40846using ::webrtc::TaskQueueTest;
847
848INSTANTIATE_TEST_SUITE_P(RtcThread,
849 TaskQueueTest,
Ali Tofigh4b681942022-08-23 10:57:16850 ::testing::Values(CreateDefaultThreadFactory));
Danil Chapovalov912b3b82019-11-22 14:52:40851
Mirko Bonadeie10b1632018-12-11 17:43:40852} // namespace
853} // namespace rtc