Support re-entrant calls to MessageQueueManager::Clear.
BUG=webrtc:7908
Review-Url: https://codereview.webrtc.org/2968753002
Cr-Commit-Position: refs/heads/master@{#18923}
diff --git a/webrtc/rtc_base/messagequeue.cc b/webrtc/rtc_base/messagequeue.cc
index c22cea7..fac7609 100644
--- a/webrtc/rtc_base/messagequeue.cc
+++ b/webrtc/rtc_base/messagequeue.cc
@@ -23,26 +23,25 @@
const int kMaxMsgLatency = 150; // 150 ms
const int kSlowDispatchLoggingThreshold = 50; // 50 ms
-class SCOPED_LOCKABLE DebugNonReentrantCritScope {
+class SCOPED_LOCKABLE MarkProcessingCritScope {
public:
- DebugNonReentrantCritScope(const CriticalSection* cs, bool* locked)
+ MarkProcessingCritScope(const CriticalSection* cs, size_t* processing)
EXCLUSIVE_LOCK_FUNCTION(cs)
- : cs_(cs), locked_(locked) {
+ : cs_(cs), processing_(processing) {
cs_->Enter();
- RTC_DCHECK(!*locked_);
- *locked_ = true;
+ *processing_ += 1;
}
- ~DebugNonReentrantCritScope() UNLOCK_FUNCTION() {
- *locked_ = false;
+ ~MarkProcessingCritScope() UNLOCK_FUNCTION() {
+ *processing_ -= 1;
cs_->Leave();
}
private:
const CriticalSection* const cs_;
- bool* locked_;
+ size_t* processing_;
- RTC_DISALLOW_COPY_AND_ASSIGN(DebugNonReentrantCritScope);
+ RTC_DISALLOW_COPY_AND_ASSIGN(MarkProcessingCritScope);
};
class FunctorPostMessageHandler : public MessageHandler {
@@ -73,7 +72,7 @@
return instance_ != nullptr;
}
-MessageQueueManager::MessageQueueManager() : locked_(false) {}
+MessageQueueManager::MessageQueueManager() : processing_(0) {}
MessageQueueManager::~MessageQueueManager() {
}
@@ -82,7 +81,9 @@
return Instance()->AddInternal(message_queue);
}
void MessageQueueManager::AddInternal(MessageQueue *message_queue) {
- DebugNonReentrantCritScope cs(&crit_, &locked_);
+ CritScope cs(&crit_);
+ // Prevent changes while the list of message queues is processed.
+ RTC_DCHECK_EQ(processing_, 0);
message_queues_.push_back(message_queue);
}
@@ -99,7 +100,9 @@
// the ThreadManager is destroyed, and threads are no longer active).
bool destroy = false;
{
- DebugNonReentrantCritScope cs(&crit_, &locked_);
+ CritScope cs(&crit_);
+ // Prevent changes while the list of message queues is processed.
+ RTC_DCHECK_EQ(processing_, 0);
std::vector<MessageQueue *>::iterator iter;
iter = std::find(message_queues_.begin(), message_queues_.end(),
message_queue);
@@ -121,10 +124,14 @@
return Instance()->ClearInternal(handler);
}
void MessageQueueManager::ClearInternal(MessageHandler *handler) {
- DebugNonReentrantCritScope cs(&crit_, &locked_);
+ // Deleted objects may cause re-entrant calls to ClearInternal. This is
+ // allowed as the list of message queues does not change while queues are
+ // cleared.
+ MarkProcessingCritScope cs(&crit_, &processing_);
std::vector<MessageQueue *>::iterator iter;
- for (iter = message_queues_.begin(); iter != message_queues_.end(); iter++)
- (*iter)->Clear(handler);
+ for (MessageQueue* queue : message_queues_) {
+ queue->Clear(handler);
+ }
}
void MessageQueueManager::ProcessAllMessageQueues() {
@@ -154,7 +161,7 @@
};
{
- DebugNonReentrantCritScope cs(&crit_, &locked_);
+ MarkProcessingCritScope cs(&crit_, &processing_);
for (MessageQueue* queue : message_queues_) {
if (!queue->IsProcessingMessages()) {
// If the queue is not processing messages, it can