Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: webrtc/base/asyncinvoker.cc

Issue 2846593005: Relanding #2: Fixing crash that can occur if signal is modified while firing. (Closed)
Patch Set: Fixing issue with disconnect_all, adding test, simplifying code a bit Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/asyncinvoker.h ('k') | webrtc/base/sigslot.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/base/asyncinvoker.h" 11 #include "webrtc/base/asyncinvoker.h"
12 12
13 #include "webrtc/base/atomicops.h" 13 #include "webrtc/base/atomicops.h"
14 #include "webrtc/base/checks.h" 14 #include "webrtc/base/checks.h"
15 #include "webrtc/base/logging.h" 15 #include "webrtc/base/logging.h"
16 16
17 namespace rtc { 17 namespace rtc {
18 18
19 AsyncInvoker::AsyncInvoker() : invocation_complete_(false, false) {} 19 AsyncInvoker::AsyncInvoker() : invocation_complete_(false, false) {}
20 20
21 AsyncInvoker::~AsyncInvoker() { 21 AsyncInvoker::~AsyncInvoker() {
22 destroying_ = true; 22 destroying_ = true;
23 SignalInvokerDestroyed();
24 // Messages for this need to be cleared *before* our destructor is complete. 23 // Messages for this need to be cleared *before* our destructor is complete.
25 MessageQueueManager::Clear(this); 24 MessageQueueManager::Clear(this);
26 // And we need to wait for any invocations that are still in progress on 25 // And we need to wait for any invocations that are still in progress on
27 // other threads. 26 // other threads.
28 while (AtomicOps::AcquireLoad(&pending_invocations_)) { 27 while (AtomicOps::AcquireLoad(&pending_invocations_)) {
29 // If the destructor was called while AsyncInvoke was being called by 28 // If the destructor was called while AsyncInvoke was being called by
30 // another thread, WITHIN an AsyncInvoked functor, it may do another 29 // another thread, WITHIN an AsyncInvoked functor, it may do another
31 // Thread::Post even after we called MessageQueueManager::Clear(this). So 30 // Thread::Post even after we called MessageQueueManager::Clear(this). So
32 // we need to keep calling Clear to discard these posts. 31 // we need to keep calling Clear to discard these posts.
33 MessageQueueManager::Clear(this); 32 MessageQueueManager::Clear(this);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 118
120 NotifyingAsyncClosureBase::NotifyingAsyncClosureBase( 119 NotifyingAsyncClosureBase::NotifyingAsyncClosureBase(
121 AsyncInvoker* invoker, 120 AsyncInvoker* invoker,
122 const Location& callback_posted_from, 121 const Location& callback_posted_from,
123 Thread* calling_thread) 122 Thread* calling_thread)
124 : AsyncClosure(invoker), 123 : AsyncClosure(invoker),
125 callback_posted_from_(callback_posted_from), 124 callback_posted_from_(callback_posted_from),
126 calling_thread_(calling_thread) { 125 calling_thread_(calling_thread) {
127 calling_thread->SignalQueueDestroyed.connect( 126 calling_thread->SignalQueueDestroyed.connect(
128 this, &NotifyingAsyncClosureBase::CancelCallback); 127 this, &NotifyingAsyncClosureBase::CancelCallback);
129 invoker->SignalInvokerDestroyed.connect( 128 // Note: We don't need to listen for the invoker being destroyed, because it
130 this, &NotifyingAsyncClosureBase::CancelCallback); 129 // will wait for this closure to be destroyed (and pending_invocations_ to go
130 // to 0) before its destructor completes.
131 } 131 }
132 132
133 NotifyingAsyncClosureBase::~NotifyingAsyncClosureBase() { 133 NotifyingAsyncClosureBase::~NotifyingAsyncClosureBase() {
134 disconnect_all(); 134 disconnect_all();
135 } 135 }
136 136
137 void NotifyingAsyncClosureBase::TriggerCallback() { 137 void NotifyingAsyncClosureBase::TriggerCallback() {
138 CritScope cs(&crit_); 138 CritScope cs(&crit_);
139 if (!CallbackCanceled() && !callback_.empty()) { 139 if (!CallbackCanceled() && !callback_.empty()) {
140 invoker_->AsyncInvoke<void>(callback_posted_from_, calling_thread_, 140 invoker_->AsyncInvoke<void>(callback_posted_from_, calling_thread_,
141 callback_); 141 callback_);
142 } 142 }
143 } 143 }
144 144
145 void NotifyingAsyncClosureBase::CancelCallback() { 145 void NotifyingAsyncClosureBase::CancelCallback() {
146 // If the callback is triggering when this is called, block the 146 // If the callback is triggering when this is called, block the
147 // destructor of the dying object here by waiting until the callback 147 // destructor of the dying object here by waiting until the callback
148 // is done triggering. 148 // is done triggering.
149 CritScope cs(&crit_); 149 CritScope cs(&crit_);
150 // calling_thread_ == nullptr means do not trigger the callback. 150 // calling_thread_ == nullptr means do not trigger the callback.
151 calling_thread_ = nullptr; 151 calling_thread_ = nullptr;
152 } 152 }
153 153
154 } // namespace rtc 154 } // namespace rtc
OLDNEW
« no previous file with comments | « webrtc/base/asyncinvoker.h ('k') | webrtc/base/sigslot.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698