blob: 885d7b8350d779f42071f6d808861fc347ffce13 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_THREAD_H_
12#define RTC_BASE_THREAD_H_
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stdint.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020016#include <list>
Sebastian Janssonda7267a2020-03-03 10:48:05 +010017#include <map>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020018#include <memory>
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +010019#include <queue>
Sebastian Janssonda7267a2020-03-03 10:48:05 +010020#include <set>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020021#include <string>
Yves Gerey988cc082018-10-23 12:03:01 +020022#include <type_traits>
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +010023#include <vector>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000024
Ali Tofigh7fa90572022-03-17 15:47:49 +010025#include "absl/strings/string_view.h"
26
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020027#if defined(WEBRTC_POSIX)
28#include <pthread.h>
29#endif
Henrik Boström2deee4b2022-01-20 11:58:05 +010030#include "absl/base/attributes.h"
Danil Chapovalov89313452019-11-29 12:56:43 +010031#include "api/function_view.h"
Danil Chapovalov912b3b82019-11-22 15:52:40 +010032#include "api/task_queue/queued_task.h"
33#include "api/task_queue/task_queue_base.h"
Artem Titovc374d112022-06-16 21:27:45 +020034#include "api/task_queue/to_queued_task.h"
Mirko Bonadei481e3452021-07-30 13:57:25 +020035#include "rtc_base/checks.h"
Markus Handell3cb525b2020-07-16 16:16:09 +020036#include "rtc_base/deprecated/recursive_critical_section.h"
Yves Gerey988cc082018-10-23 12:03:01 +020037#include "rtc_base/location.h"
Steve Anton10542f22019-01-11 09:11:00 -080038#include "rtc_base/message_handler.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020039#include "rtc_base/platform_thread_types.h"
Steve Anton10542f22019-01-11 09:11:00 -080040#include "rtc_base/socket_server.h"
Mirko Bonadei35214fc2019-09-23 14:54:28 +020041#include "rtc_base/system/rtc_export.h"
Yves Gerey988cc082018-10-23 12:03:01 +020042#include "rtc_base/thread_annotations.h"
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +010043#include "rtc_base/thread_message.h"
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020044
45#if defined(WEBRTC_WIN)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020046#include "rtc_base/win32.h"
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020047#endif
48
Tommife041642021-04-07 10:08:28 +020049#if RTC_DCHECK_IS_ON
50// Counts how many blocking Thread::Invoke or Thread::Send calls are made from
51// within a scope and logs the number of blocking calls at the end of the scope.
52#define RTC_LOG_THREAD_BLOCK_COUNT() \
53 rtc::Thread::ScopedCountBlockingCalls blocked_call_count_printer( \
54 [func = __func__](uint32_t actual_block, uint32_t could_block) { \
55 auto total = actual_block + could_block; \
56 if (total) { \
57 RTC_LOG(LS_WARNING) << "Blocking " << func << ": total=" << total \
58 << " (actual=" << actual_block \
59 << ", could=" << could_block << ")"; \
60 } \
61 })
62
63// Adds an RTC_DCHECK_LE that checks that the number of blocking calls are
64// less than or equal to a specific value. Use to avoid regressing in the
65// number of blocking thread calls.
66// Note: Use of this macro, requires RTC_LOG_THREAD_BLOCK_COUNT() to be called
67// first.
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +020068#define RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(x) \
69 do { \
70 blocked_call_count_printer.set_minimum_call_count_for_callback(x + 1); \
71 RTC_DCHECK_LE(blocked_call_count_printer.GetTotalBlockedCallCount(), x); \
72 } while (0)
Tommife041642021-04-07 10:08:28 +020073#else
74#define RTC_LOG_THREAD_BLOCK_COUNT()
75#define RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(x)
76#endif
77
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020078namespace rtc {
79
80class Thread;
81
Henrik Boströmba4dcc32019-02-28 09:34:06 +010082namespace rtc_thread_internal {
83
Niels Möllerf13a0962019-05-17 10:15:06 +020084class MessageLikeTask : public MessageData {
Henrik Boströmba4dcc32019-02-28 09:34:06 +010085 public:
Niels Möllerf13a0962019-05-17 10:15:06 +020086 virtual void Run() = 0;
87};
88
89template <class FunctorT>
90class MessageWithFunctor final : public MessageLikeTask {
91 public:
92 explicit MessageWithFunctor(FunctorT&& functor)
Henrik Boströmba4dcc32019-02-28 09:34:06 +010093 : functor_(std::forward<FunctorT>(functor)) {}
94
Byoungchan Lee14af7622022-01-12 05:24:58 +090095 MessageWithFunctor(const MessageWithFunctor&) = delete;
96 MessageWithFunctor& operator=(const MessageWithFunctor&) = delete;
97
Niels Möllerf13a0962019-05-17 10:15:06 +020098 void Run() override { functor_(); }
Henrik Boströmba4dcc32019-02-28 09:34:06 +010099
100 private:
Niels Möllerf13a0962019-05-17 10:15:06 +0200101 ~MessageWithFunctor() override {}
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100102
103 typename std::remove_reference<FunctorT>::type functor_;
Niels Möllerf13a0962019-05-17 10:15:06 +0200104};
105
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100106} // namespace rtc_thread_internal
107
Mirko Bonadei35214fc2019-09-23 14:54:28 +0200108class RTC_EXPORT ThreadManager {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200109 public:
110 static const int kForever = -1;
111
112 // Singleton, constructor and destructor are private.
113 static ThreadManager* Instance();
114
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100115 static void Add(Thread* message_queue);
116 static void Remove(Thread* message_queue);
117 static void Clear(MessageHandler* handler);
118
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100119 // For testing purposes, for use with a simulated clock.
120 // Ensures that all message queues have processed delayed messages
121 // up until the current point in time.
122 static void ProcessAllMessageQueuesForTesting();
123
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200124 Thread* CurrentThread();
125 void SetCurrentThread(Thread* thread);
Sebastian Jansson178a6852020-01-14 11:12:26 +0100126 // Allows changing the current thread, this is intended for tests where we
127 // want to simulate multiple threads running on a single physical thread.
128 void ChangeCurrentThreadForTest(Thread* thread);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200129
130 // Returns a thread object with its thread_ ivar set
131 // to whatever the OS uses to represent the thread.
132 // If there already *is* a Thread object corresponding to this thread,
133 // this method will return that. Otherwise it creates a new Thread
134 // object whose wrapped() method will return true, and whose
135 // handle will, on Win32, be opened with only synchronization privileges -
136 // if you need more privilegs, rather than changing this method, please
137 // write additional code to adjust the privileges, or call a different
138 // factory method of your own devising, because this one gets used in
139 // unexpected contexts (like inside browser plugins) and it would be a
140 // shame to break it. It is also conceivable on Win32 that we won't even
141 // be able to get synchronization privileges, in which case the result
142 // will have a null handle.
Yves Gerey665174f2018-06-19 15:03:05 +0200143 Thread* WrapCurrentThread();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200144 void UnwrapCurrentThread();
145
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100146#if RTC_DCHECK_IS_ON
Artem Titov96e3b992021-07-26 16:03:14 +0200147 // Registers that a Send operation is to be performed between `source` and
148 // `target`, while checking that this does not cause a send cycle that could
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100149 // potentially cause a deadlock.
150 void RegisterSendAndCheckForCycles(Thread* source, Thread* target);
151#endif
152
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200153 private:
154 ThreadManager();
155 ~ThreadManager();
156
Byoungchan Lee14af7622022-01-12 05:24:58 +0900157 ThreadManager(const ThreadManager&) = delete;
158 ThreadManager& operator=(const ThreadManager&) = delete;
159
Sebastian Jansson178a6852020-01-14 11:12:26 +0100160 void SetCurrentThreadInternal(Thread* thread);
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100161 void AddInternal(Thread* message_queue);
162 void RemoveInternal(Thread* message_queue);
163 void ClearInternal(MessageHandler* handler);
164 void ProcessAllMessageQueuesInternal();
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100165#if RTC_DCHECK_IS_ON
166 void RemoveFromSendGraph(Thread* thread) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
167#endif
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100168
169 // This list contains all live Threads.
170 std::vector<Thread*> message_queues_ RTC_GUARDED_BY(crit_);
171
172 // Methods that don't modify the list of message queues may be called in a
173 // re-entrant fashion. "processing_" keeps track of the depth of re-entrant
174 // calls.
Markus Handell3cb525b2020-07-16 16:16:09 +0200175 RecursiveCriticalSection crit_;
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100176 size_t processing_ RTC_GUARDED_BY(crit_) = 0;
Sebastian Janssonda7267a2020-03-03 10:48:05 +0100177#if RTC_DCHECK_IS_ON
178 // Represents all thread seand actions by storing all send targets per thread.
179 // This is used by RegisterSendAndCheckForCycles. This graph has no cycles
180 // since we will trigger a CHECK failure if a cycle is introduced.
181 std::map<Thread*, std::set<Thread*>> send_graph_ RTC_GUARDED_BY(crit_);
182#endif
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100183
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200184#if defined(WEBRTC_POSIX)
185 pthread_key_t key_;
186#endif
187
188#if defined(WEBRTC_WIN)
Tommi51492422017-12-04 15:18:23 +0100189 const DWORD key_;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200190#endif
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200191};
192
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200193// WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS! See ~Thread().
194
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100195class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
tommia8a35152017-07-13 05:47:25 -0700196 public:
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100197 static const int kForever = -1;
198
199 // Create a new Thread and optionally assign it to the passed
200 // SocketServer. Subclasses that override Clear should pass false for
201 // init_queue and call DoInit() from their constructor to prevent races
202 // with the ThreadManager using the object while the vtable is still
203 // being created.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200204 explicit Thread(SocketServer* ss);
205 explicit Thread(std::unique_ptr<SocketServer> ss);
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100206
Taylor Brandstetter08672602018-03-02 15:20:33 -0800207 // Constructors meant for subclasses; they should call DoInit themselves and
Artem Titov96e3b992021-07-26 16:03:14 +0200208 // pass false for `do_init`, so that DoInit is called only on the fully
Taylor Brandstetter08672602018-03-02 15:20:33 -0800209 // instantiated class, which avoids a vptr data race.
210 Thread(SocketServer* ss, bool do_init);
211 Thread(std::unique_ptr<SocketServer> ss, bool do_init);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200212
213 // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or
214 // guarantee Stop() is explicitly called before the subclass is destroyed).
215 // This is required to avoid a data race between the destructor modifying the
216 // vtable, and the Thread::PreRun calling the virtual method Run().
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100217
218 // NOTE: SUBCLASSES OF Thread THAT OVERRIDE Clear MUST CALL
219 // DoDestroy() IN THEIR DESTRUCTORS! This is required to avoid a data race
220 // between the destructor modifying the vtable, and the ThreadManager
221 // calling Clear on the object from a different thread.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200222 ~Thread() override;
223
Byoungchan Lee14af7622022-01-12 05:24:58 +0900224 Thread(const Thread&) = delete;
225 Thread& operator=(const Thread&) = delete;
226
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200227 static std::unique_ptr<Thread> CreateWithSocketServer();
228 static std::unique_ptr<Thread> Create();
229 static Thread* Current();
230
231 // Used to catch performance regressions. Use this to disallow blocking calls
232 // (Invoke) for a given scope. If a synchronous call is made while this is in
233 // effect, an assert will be triggered.
234 // Note that this is a single threaded class.
235 class ScopedDisallowBlockingCalls {
236 public:
237 ScopedDisallowBlockingCalls();
Sebastian Jansson9debe5a2019-03-22 15:42:38 +0100238 ScopedDisallowBlockingCalls(const ScopedDisallowBlockingCalls&) = delete;
239 ScopedDisallowBlockingCalls& operator=(const ScopedDisallowBlockingCalls&) =
240 delete;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200241 ~ScopedDisallowBlockingCalls();
Yves Gerey665174f2018-06-19 15:03:05 +0200242
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200243 private:
244 Thread* const thread_;
245 const bool previous_state_;
246 };
247
Tommife041642021-04-07 10:08:28 +0200248#if RTC_DCHECK_IS_ON
249 class ScopedCountBlockingCalls {
250 public:
251 ScopedCountBlockingCalls(std::function<void(uint32_t, uint32_t)> callback);
252 ScopedCountBlockingCalls(const ScopedDisallowBlockingCalls&) = delete;
253 ScopedCountBlockingCalls& operator=(const ScopedDisallowBlockingCalls&) =
254 delete;
255 ~ScopedCountBlockingCalls();
256
257 uint32_t GetBlockingCallCount() const;
258 uint32_t GetCouldBeBlockingCallCount() const;
259 uint32_t GetTotalBlockedCallCount() const;
260
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200261 void set_minimum_call_count_for_callback(uint32_t minimum) {
262 min_blocking_calls_for_callback_ = minimum;
263 }
264
Tommife041642021-04-07 10:08:28 +0200265 private:
266 Thread* const thread_;
267 const uint32_t base_blocking_call_count_;
268 const uint32_t base_could_be_blocking_call_count_;
Tomas Gunnarsson89f3dd52021-04-14 12:54:10 +0200269 // The minimum number of blocking calls required in order to issue the
270 // result_callback_. This is used by RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN to
271 // tame log spam.
272 // By default we always issue the callback, regardless of callback count.
273 uint32_t min_blocking_calls_for_callback_ = 0;
Tommife041642021-04-07 10:08:28 +0200274 std::function<void(uint32_t, uint32_t)> result_callback_;
275 };
276
277 uint32_t GetBlockingCallCount() const;
278 uint32_t GetCouldBeBlockingCallCount() const;
279#endif
280
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100281 SocketServer* socketserver();
282
283 // Note: The behavior of Thread has changed. When a thread is stopped,
284 // futher Posts and Sends will fail. However, any pending Sends and *ready*
285 // Posts (as opposed to unexpired delayed Posts) will be delivered before
286 // Get (or Peek) returns false. By guaranteeing delivery of those messages,
287 // we eliminate the race condition when an MessageHandler and Thread
288 // may be destroyed independently of each other.
289 virtual void Quit();
290 virtual bool IsQuitting();
291 virtual void Restart();
292 // Not all message queues actually process messages (such as SignalThread).
293 // In those cases, it's important to know, before posting, that it won't be
294 // Processed. Normally, this would be true until IsQuitting() is true.
295 virtual bool IsProcessingMessagesForTesting();
296
297 // Get() will process I/O until:
298 // 1) A message is available (returns true)
299 // 2) cmsWait seconds have elapsed (returns false)
300 // 3) Stop() is called (returns false)
301 virtual bool Get(Message* pmsg,
302 int cmsWait = kForever,
303 bool process_io = true);
304 virtual bool Peek(Message* pmsg, int cmsWait = 0);
Artem Titov96e3b992021-07-26 16:03:14 +0200305 // `time_sensitive` is deprecated and should always be false.
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100306 virtual void Post(const Location& posted_from,
307 MessageHandler* phandler,
308 uint32_t id = 0,
309 MessageData* pdata = nullptr,
310 bool time_sensitive = false);
311 virtual void PostDelayed(const Location& posted_from,
Sebastian Jansson61380c02020-01-17 14:46:08 +0100312 int delay_ms,
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100313 MessageHandler* phandler,
314 uint32_t id = 0,
315 MessageData* pdata = nullptr);
316 virtual void PostAt(const Location& posted_from,
Sebastian Jansson61380c02020-01-17 14:46:08 +0100317 int64_t run_at_ms,
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100318 MessageHandler* phandler,
319 uint32_t id = 0,
320 MessageData* pdata = nullptr);
321 virtual void Clear(MessageHandler* phandler,
322 uint32_t id = MQID_ANY,
323 MessageList* removed = nullptr);
324 virtual void Dispatch(Message* pmsg);
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100325
326 // Amount of time until the next message can be retrieved
327 virtual int GetDelay();
328
329 bool empty() const { return size() == 0u; }
330 size_t size() const {
Sebastian Jansson61380c02020-01-17 14:46:08 +0100331 CritScope cs(&crit_);
332 return messages_.size() + delayed_messages_.size() + (fPeekKeep_ ? 1u : 0u);
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100333 }
334
335 // Internally posts a message which causes the doomed object to be deleted
336 template <class T>
337 void Dispose(T* doomed) {
338 if (doomed) {
339 Post(RTC_FROM_HERE, nullptr, MQID_DISPOSE, new DisposeData<T>(doomed));
340 }
341 }
342
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200343 bool IsCurrent() const;
344
345 // Sleeps the calling thread for the specified number of milliseconds, during
346 // which time no processing is performed. Returns false if sleeping was
347 // interrupted by a signal (POSIX only).
348 static bool SleepMs(int millis);
349
350 // Sets the thread's name, for debugging. Must be called before Start().
Artem Titov96e3b992021-07-26 16:03:14 +0200351 // If `obj` is non-null, its value is appended to `name`.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200352 const std::string& name() const { return name_; }
Ali Tofigh7fa90572022-03-17 15:47:49 +0100353 bool SetName(absl::string_view name, const void* obj);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200354
Harald Alvestrandba694422021-01-27 21:52:14 +0000355 // Sets the expected processing time in ms. The thread will write
356 // log messages when Invoke() takes more time than this.
357 // Default is 50 ms.
358 void SetDispatchWarningMs(int deadline);
359
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200360 // Starts the execution of the thread.
Niels Möllerd2e50132019-06-11 09:24:14 +0200361 bool Start();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200362
363 // Tells the thread to stop and waits until it is joined.
364 // Never call Stop on the current thread. Instead use the inherited Quit
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100365 // function which will exit the base Thread without terminating the
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200366 // underlying OS thread.
367 virtual void Stop();
368
369 // By default, Thread::Run() calls ProcessMessages(kForever). To do other
370 // work, override Run(). To receive and dispatch messages, call
371 // ProcessMessages occasionally.
372 virtual void Run();
373
374 virtual void Send(const Location& posted_from,
375 MessageHandler* phandler,
376 uint32_t id = 0,
377 MessageData* pdata = nullptr);
378
379 // Convenience method to invoke a functor on another thread. Caller must
Artem Titov96e3b992021-07-26 16:03:14 +0200380 // provide the `ReturnT` template argument, which cannot (easily) be deduced.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200381 // Uses Send() internally, which blocks the current thread until execution
382 // is complete.
383 // Ex: bool result = thread.Invoke<bool>(RTC_FROM_HERE,
384 // &MyFunctionReturningBool);
385 // NOTE: This function can only be called when synchronous calls are allowed.
386 // See ScopedDisallowBlockingCalls for details.
Henrik Boströmba4dcc32019-02-28 09:34:06 +0100387 // NOTE: Blocking invokes are DISCOURAGED, consider if what you're doing can
388 // be achieved with PostTask() and callbacks instead.
Danil Chapovalov89313452019-11-29 12:56:43 +0100389 template <
390 class ReturnT,
391 typename = typename std::enable_if<!std::is_void<ReturnT>::value>::type>
392 ReturnT Invoke(const Location& posted_from, FunctionView<ReturnT()> functor) {
393 ReturnT result;
394 InvokeInternal(posted_from, [functor, &result] { result = functor(); });
395 return result;
396 }
397
398 template <
399 class ReturnT,
400 typename = typename std::enable_if<std::is_void<ReturnT>::value>::type>
401 void Invoke(const Location& posted_from, FunctionView<void()> functor) {
402 InvokeInternal(posted_from, functor);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200403 }
404
Artem Titov96e3b992021-07-26 16:03:14 +0200405 // Allows invoke to specified `thread`. Thread never will be dereferenced and
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200406 // will be used only for reference-based comparison, so instance can be safely
Mirko Bonadei481e3452021-07-30 13:57:25 +0200407 // deleted. If NDEBUG is defined and RTC_DCHECK_IS_ON is undefined do
Mirko Bonadei8c185fc2021-07-21 13:12:38 +0200408 // nothing.
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200409 void AllowInvokesToThread(Thread* thread);
Tomas Gunnarssonabdb4702020-09-05 18:43:36 +0200410
Mirko Bonadei481e3452021-07-30 13:57:25 +0200411 // If NDEBUG is defined and RTC_DCHECK_IS_ON is undefined do nothing.
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200412 void DisallowAllInvokes();
Artem Titov96e3b992021-07-26 16:03:14 +0200413 // Returns true if `target` was allowed by AllowInvokesToThread() or if no
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200414 // calls were made to AllowInvokesToThread and DisallowAllInvokes. Otherwise
415 // returns false.
Mirko Bonadei481e3452021-07-30 13:57:25 +0200416 // If NDEBUG is defined and RTC_DCHECK_IS_ON is undefined always returns
Mirko Bonadei8c185fc2021-07-21 13:12:38 +0200417 // true.
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200418 bool IsInvokeToThreadAllowed(rtc::Thread* target);
419
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100420 // From TaskQueueBase
421 void PostTask(std::unique_ptr<webrtc::QueuedTask> task) override;
422 void PostDelayedTask(std::unique_ptr<webrtc::QueuedTask> task,
423 uint32_t milliseconds) override;
Henrik Boströmcf9899c2022-01-20 09:46:16 +0100424 void PostDelayedHighPrecisionTask(std::unique_ptr<webrtc::QueuedTask> task,
425 uint32_t milliseconds) override;
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100426 void Delete() override;
427
Henrik Boström2deee4b2022-01-20 11:58:05 +0100428 // Helper methods to avoid having to do ToQueuedTask() at the calling places.
429 template <class Closure,
430 typename std::enable_if<!std::is_convertible<
431 Closure,
432 std::unique_ptr<webrtc::QueuedTask>>::value>::type* = nullptr>
433 void PostTask(Closure&& closure) {
434 PostTask(webrtc::ToQueuedTask(std::forward<Closure>(closure)));
435 }
436 template <class Closure,
437 typename std::enable_if<!std::is_convertible<
438 Closure,
439 std::unique_ptr<webrtc::QueuedTask>>::value>::type* = nullptr>
440 void PostDelayedTask(Closure&& closure, uint32_t milliseconds) {
441 PostDelayedTask(webrtc::ToQueuedTask(std::forward<Closure>(closure)),
442 milliseconds);
443 }
444 template <class Closure,
445 typename std::enable_if<!std::is_convertible<
446 Closure,
447 std::unique_ptr<webrtc::QueuedTask>>::value>::type* = nullptr>
448 void PostDelayedHighPrecisionTask(Closure&& closure, uint32_t milliseconds) {
449 PostDelayedHighPrecisionTask(
450 webrtc::ToQueuedTask(std::forward<Closure>(closure)), milliseconds);
451 }
452
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200453 // ProcessMessages will process I/O and dispatch messages until:
454 // 1) cms milliseconds have elapsed (returns true)
455 // 2) Stop() is called (returns false)
456 bool ProcessMessages(int cms);
457
458 // Returns true if this is a thread that we created using the standard
459 // constructor, false if it was created by a call to
460 // ThreadManager::WrapCurrentThread(). The main thread of an application
461 // is generally not owned, since the OS representation of the thread
462 // obviously exists before we can get to it.
463 // You cannot call Start on non-owned threads.
464 bool IsOwned();
465
Tommi51492422017-12-04 15:18:23 +0100466 // Expose private method IsRunning() for tests.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200467 //
468 // DANGER: this is a terrible public API. Most callers that might want to
469 // call this likely do not have enough control/knowledge of the Thread in
470 // question to guarantee that the returned value remains true for the duration
471 // of whatever code is conditionally executing because of the return value!
Tommi51492422017-12-04 15:18:23 +0100472 bool RunningForTest() { return IsRunning(); }
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200473
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200474 // These functions are public to avoid injecting test hooks. Don't call them
475 // outside of tests.
476 // This method should be called when thread is created using non standard
477 // method, like derived implementation of rtc::Thread and it can not be
478 // started by calling Start(). This will set started flag to true and
479 // owned to false. This must be called from the current thread.
480 bool WrapCurrent();
481 void UnwrapCurrent();
482
Karl Wiberg32562252019-02-21 13:38:30 +0100483 // Sets the per-thread allow-blocking-calls flag to false; this is
484 // irrevocable. Must be called on this thread.
485 void DisallowBlockingCalls() { SetAllowBlockingCalls(false); }
486
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200487 protected:
Sebastian Jansson6ce033a2020-01-22 10:12:56 +0100488 class CurrentThreadSetter : CurrentTaskQueueSetter {
489 public:
490 explicit CurrentThreadSetter(Thread* thread)
491 : CurrentTaskQueueSetter(thread),
492 manager_(rtc::ThreadManager::Instance()),
493 previous_(manager_->CurrentThread()) {
494 manager_->ChangeCurrentThreadForTest(thread);
495 }
496 ~CurrentThreadSetter() { manager_->ChangeCurrentThreadForTest(previous_); }
497
498 private:
499 rtc::ThreadManager* const manager_;
500 rtc::Thread* const previous_;
501 };
502
Sebastian Jansson61380c02020-01-17 14:46:08 +0100503 // DelayedMessage goes into a priority queue, sorted by trigger time. Messages
504 // with the same trigger time are processed in num_ (FIFO) order.
505 class DelayedMessage {
506 public:
507 DelayedMessage(int64_t delay,
508 int64_t run_time_ms,
509 uint32_t num,
510 const Message& msg)
511 : delay_ms_(delay),
512 run_time_ms_(run_time_ms),
513 message_number_(num),
514 msg_(msg) {}
515
516 bool operator<(const DelayedMessage& dmsg) const {
517 return (dmsg.run_time_ms_ < run_time_ms_) ||
518 ((dmsg.run_time_ms_ == run_time_ms_) &&
519 (dmsg.message_number_ < message_number_));
520 }
521
522 int64_t delay_ms_; // for debugging
523 int64_t run_time_ms_;
524 // Monotonicaly incrementing number used for ordering of messages
525 // targeted to execute at the same time.
526 uint32_t message_number_;
527 Message msg_;
528 };
529
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100530 class PriorityQueue : public std::priority_queue<DelayedMessage> {
531 public:
532 container_type& container() { return c; }
533 void reheap() { make_heap(c.begin(), c.end(), comp); }
534 };
535
536 void DoDelayPost(const Location& posted_from,
537 int64_t cmsDelay,
538 int64_t tstamp,
539 MessageHandler* phandler,
540 uint32_t id,
541 MessageData* pdata);
542
543 // Perform initialization, subclasses must call this from their constructor
544 // if false was passed as init_queue to the Thread constructor.
545 void DoInit();
546
547 // Does not take any lock. Must be called either while holding crit_, or by
548 // the destructor (by definition, the latter has exclusive access).
549 void ClearInternal(MessageHandler* phandler,
550 uint32_t id,
551 MessageList* removed) RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_);
552
553 // Perform cleanup; subclasses must call this from the destructor,
554 // and are not expected to actually hold the lock.
555 void DoDestroy() RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_);
556
557 void WakeUpSocketServer();
558
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200559 // Same as WrapCurrent except that it never fails as it does not try to
560 // acquire the synchronization access of the thread. The caller should never
561 // call Stop() or Join() on this thread.
562 void SafeWrapCurrent();
563
564 // Blocks the calling thread until this thread has terminated.
565 void Join();
566
567 static void AssertBlockingIsAllowedOnCurrentThread();
568
569 friend class ScopedDisallowBlockingCalls;
570
Markus Handell3cb525b2020-07-16 16:16:09 +0200571 RecursiveCriticalSection* CritForTest() { return &crit_; }
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100572
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200573 private:
Harald Alvestrandba694422021-01-27 21:52:14 +0000574 static const int kSlowDispatchLoggingThreshold = 50; // 50 ms
575
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100576 class QueuedTaskHandler final : public MessageHandler {
577 public:
Tomas Gunnarsson77baeee2020-09-24 22:39:21 +0200578 QueuedTaskHandler() {}
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100579 void OnMessage(Message* msg) override;
580 };
Steve Antonbcc1a762019-12-11 11:21:53 -0800581
Karl Wiberg32562252019-02-21 13:38:30 +0100582 // Sets the per-thread allow-blocking-calls flag and returns the previous
583 // value. Must be called on this thread.
584 bool SetAllowBlockingCalls(bool allow);
585
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200586#if defined(WEBRTC_WIN)
587 static DWORD WINAPI PreRun(LPVOID context);
588#else
Yves Gerey665174f2018-06-19 15:03:05 +0200589 static void* PreRun(void* pv);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200590#endif
591
592 // ThreadManager calls this instead WrapCurrent() because
593 // ThreadManager::Instance() cannot be used while ThreadManager is
594 // being created.
595 // The method tries to get synchronization rights of the thread on Windows if
Artem Titov96e3b992021-07-26 16:03:14 +0200596 // `need_synchronize_access` is true.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200597 bool WrapCurrentWithThreadManager(ThreadManager* thread_manager,
598 bool need_synchronize_access);
599
Tommi51492422017-12-04 15:18:23 +0100600 // Return true if the thread is currently running.
601 bool IsRunning();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200602
Danil Chapovalov89313452019-11-29 12:56:43 +0100603 void InvokeInternal(const Location& posted_from,
604 rtc::FunctionView<void()> functor);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200605
Tommi6866dc72020-05-15 10:11:56 +0200606 // Called by the ThreadManager when being set as the current thread.
607 void EnsureIsCurrentTaskQueue();
608
609 // Called by the ThreadManager when being unset as the current thread.
610 void ClearCurrentTaskQueue();
611
Steve Antonbcc1a762019-12-11 11:21:53 -0800612 // Returns a static-lifetime MessageHandler which runs message with
613 // MessageLikeTask payload data.
614 static MessageHandler* GetPostTaskMessageHandler();
615
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100616 bool fPeekKeep_;
617 Message msgPeek_;
Sebastian Jansson61380c02020-01-17 14:46:08 +0100618 MessageList messages_ RTC_GUARDED_BY(crit_);
619 PriorityQueue delayed_messages_ RTC_GUARDED_BY(crit_);
620 uint32_t delayed_next_num_ RTC_GUARDED_BY(crit_);
Tommife041642021-04-07 10:08:28 +0200621#if RTC_DCHECK_IS_ON
622 uint32_t blocking_call_count_ RTC_GUARDED_BY(this) = 0;
623 uint32_t could_be_blocking_call_count_ RTC_GUARDED_BY(this) = 0;
Artem Titovdfc5f0d2020-07-03 12:09:26 +0200624 std::vector<Thread*> allowed_threads_ RTC_GUARDED_BY(this);
625 bool invoke_policy_enabled_ RTC_GUARDED_BY(this) = false;
626#endif
Markus Handell3cb525b2020-07-16 16:16:09 +0200627 RecursiveCriticalSection crit_;
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100628 bool fInitialized_;
629 bool fDestroyed_;
630
631 volatile int stop_;
632
633 // The SocketServer might not be owned by Thread.
634 SocketServer* const ss_;
Artem Titov96e3b992021-07-26 16:03:14 +0200635 // Used if SocketServer ownership lies with `this`.
Sebastian Jansson6ea2c6a2020-01-13 14:07:22 +0100636 std::unique_ptr<SocketServer> own_ss_;
637
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200638 std::string name_;
Tommi51492422017-12-04 15:18:23 +0100639
Jonas Olssona4d87372019-07-05 19:08:33 +0200640 // TODO(tommi): Add thread checks for proper use of control methods.
641 // Ideally we should be able to just use PlatformThread.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200642
643#if defined(WEBRTC_POSIX)
Tommi6cea2b02017-12-04 18:51:16 +0100644 pthread_t thread_ = 0;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200645#endif
646
647#if defined(WEBRTC_WIN)
Tommi6cea2b02017-12-04 18:51:16 +0100648 HANDLE thread_ = nullptr;
649 DWORD thread_id_ = 0;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200650#endif
651
Tommi51492422017-12-04 15:18:23 +0100652 // Indicates whether or not ownership of the worker thread lies with
653 // this instance or not. (i.e. owned_ == !wrapped).
654 // Must only be modified when the worker thread is not running.
655 bool owned_ = true;
656
657 // Only touched from the worker thread itself.
658 bool blocking_calls_allowed_ = true;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200659
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100660 // Runs webrtc::QueuedTask posted to the Thread.
661 QueuedTaskHandler queued_task_handler_;
Tommi6866dc72020-05-15 10:11:56 +0200662 std::unique_ptr<TaskQueueBase::CurrentTaskQueueSetter>
663 task_queue_registration_;
Danil Chapovalov912b3b82019-11-22 15:52:40 +0100664
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200665 friend class ThreadManager;
666
Harald Alvestrandba694422021-01-27 21:52:14 +0000667 int dispatch_warning_ms_ RTC_GUARDED_BY(this) = kSlowDispatchLoggingThreshold;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200668};
669
670// AutoThread automatically installs itself at construction
671// uninstalls at destruction, if a Thread object is
672// _not already_ associated with the current OS thread.
Tomas Gunnarsson0fd4c4e2020-09-04 16:33:25 +0200673//
674// NOTE: *** This class should only be used by tests ***
675//
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200676class AutoThread : public Thread {
677 public:
678 AutoThread();
679 ~AutoThread() override;
680
Byoungchan Lee14af7622022-01-12 05:24:58 +0900681 AutoThread(const AutoThread&) = delete;
682 AutoThread& operator=(const AutoThread&) = delete;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200683};
684
685// AutoSocketServerThread automatically installs itself at
686// construction and uninstalls at destruction. If a Thread object is
687// already associated with the current OS thread, it is temporarily
688// disassociated and restored by the destructor.
689
690class AutoSocketServerThread : public Thread {
691 public:
692 explicit AutoSocketServerThread(SocketServer* ss);
693 ~AutoSocketServerThread() override;
694
Byoungchan Lee14af7622022-01-12 05:24:58 +0900695 AutoSocketServerThread(const AutoSocketServerThread&) = delete;
696 AutoSocketServerThread& operator=(const AutoSocketServerThread&) = delete;
697
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200698 private:
699 rtc::Thread* old_thread_;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200700};
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200701} // namespace rtc
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000702
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200703#endif // RTC_BASE_THREAD_H_