blob: cc9cde59c07535f24becfa96ef4807b78438b4e3 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2014 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
11#include "webrtc/base/asyncinvoker.h"
12
Magnus Jedverta1f590f2015-08-20 16:42:42 +020013#include "webrtc/base/checks.h"
Per33544192015-04-02 12:30:51 +020014#include "webrtc/base/logging.h"
15
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000016namespace rtc {
17
18AsyncInvoker::AsyncInvoker() : destroying_(false) {}
19
20AsyncInvoker::~AsyncInvoker() {
21 destroying_ = true;
22 SignalInvokerDestroyed();
23 // Messages for this need to be cleared *before* our destructor is complete.
24 MessageQueueManager::Clear(this);
25}
26
27void AsyncInvoker::OnMessage(Message* msg) {
28 // Get the AsyncClosure shared ptr from this message's data.
deadbeefa5a47292017-02-17 15:19:19 -080029 ScopedMessageData<AsyncClosure>* data =
30 static_cast<ScopedMessageData<AsyncClosure>*>(msg->pdata);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031 // Execute the closure and trigger the return message if needed.
deadbeefa5a47292017-02-17 15:19:19 -080032 data->data().Execute();
33 delete data;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000034}
35
Peter Boström0c4e06b2015-10-07 12:23:21 +020036void AsyncInvoker::Flush(Thread* thread, uint32_t id /*= MQID_ANY*/) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000037 if (destroying_) return;
38
39 // Run this on |thread| to reduce the number of context switches.
40 if (Thread::Current() != thread) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070041 thread->Invoke<void>(RTC_FROM_HERE,
42 Bind(&AsyncInvoker::Flush, this, thread, id));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000043 return;
44 }
45
46 MessageList removed;
47 thread->Clear(this, id, &removed);
48 for (MessageList::iterator it = removed.begin(); it != removed.end(); ++it) {
49 // This message was pending on this thread, so run it now.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070050 thread->Send(it->posted_from, it->phandler, it->message_id, it->pdata);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051 }
52}
53
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070054void AsyncInvoker::DoInvoke(const Location& posted_from,
55 Thread* thread,
deadbeefa5a47292017-02-17 15:19:19 -080056 std::unique_ptr<AsyncClosure> closure,
Peter Boström0c4e06b2015-10-07 12:23:21 +020057 uint32_t id) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000058 if (destroying_) {
59 LOG(LS_WARNING) << "Tried to invoke while destroying the invoker.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000060 return;
61 }
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070062 thread->Post(posted_from, this, id,
deadbeefa5a47292017-02-17 15:19:19 -080063 new ScopedMessageData<AsyncClosure>(std::move(closure)));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000064}
65
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070066void AsyncInvoker::DoInvokeDelayed(const Location& posted_from,
67 Thread* thread,
deadbeefa5a47292017-02-17 15:19:19 -080068 std::unique_ptr<AsyncClosure> closure,
Peter Boström0c4e06b2015-10-07 12:23:21 +020069 uint32_t delay_ms,
70 uint32_t id) {
Guo-wei Shiehdc13abc2015-06-18 14:44:41 -070071 if (destroying_) {
72 LOG(LS_WARNING) << "Tried to invoke while destroying the invoker.";
73 return;
74 }
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070075 thread->PostDelayed(posted_from, delay_ms, this, id,
deadbeefa5a47292017-02-17 15:19:19 -080076 new ScopedMessageData<AsyncClosure>(std::move(closure)));
Guo-wei Shiehdc13abc2015-06-18 14:44:41 -070077}
78
Magnus Jedverta1f590f2015-08-20 16:42:42 +020079GuardedAsyncInvoker::GuardedAsyncInvoker() : thread_(Thread::Current()) {
80 thread_->SignalQueueDestroyed.connect(this,
81 &GuardedAsyncInvoker::ThreadDestroyed);
82}
83
84GuardedAsyncInvoker::~GuardedAsyncInvoker() {
85}
86
Peter Boström0c4e06b2015-10-07 12:23:21 +020087bool GuardedAsyncInvoker::Flush(uint32_t id) {
Magnus Jedverta1f590f2015-08-20 16:42:42 +020088 rtc::CritScope cs(&crit_);
89 if (thread_ == nullptr)
90 return false;
91 invoker_.Flush(thread_, id);
92 return true;
93}
94
95void GuardedAsyncInvoker::ThreadDestroyed() {
96 rtc::CritScope cs(&crit_);
97 // We should never get more than one notification about the thread dying.
henrikg91d6ede2015-09-17 00:24:34 -070098 RTC_DCHECK(thread_ != nullptr);
Magnus Jedverta1f590f2015-08-20 16:42:42 +020099 thread_ = nullptr;
100}
101
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700102NotifyingAsyncClosureBase::NotifyingAsyncClosureBase(
103 AsyncInvoker* invoker,
104 const Location& callback_posted_from,
105 Thread* calling_thread)
106 : invoker_(invoker),
107 callback_posted_from_(callback_posted_from),
108 calling_thread_(calling_thread) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000109 calling_thread->SignalQueueDestroyed.connect(
110 this, &NotifyingAsyncClosureBase::CancelCallback);
111 invoker->SignalInvokerDestroyed.connect(
112 this, &NotifyingAsyncClosureBase::CancelCallback);
113}
114
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000115NotifyingAsyncClosureBase::~NotifyingAsyncClosureBase() {
116 disconnect_all();
117}
118
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000119void NotifyingAsyncClosureBase::TriggerCallback() {
120 CritScope cs(&crit_);
121 if (!CallbackCanceled() && !callback_.empty()) {
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700122 invoker_->AsyncInvoke<void>(callback_posted_from_, calling_thread_,
123 callback_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000124 }
125}
126
127void NotifyingAsyncClosureBase::CancelCallback() {
128 // If the callback is triggering when this is called, block the
129 // destructor of the dying object here by waiting until the callback
130 // is done triggering.
131 CritScope cs(&crit_);
132 // calling_thread_ == NULL means do not trigger the callback.
133 calling_thread_ = NULL;
134}
135
136} // namespace rtc