Index: webrtc/rtc_base/messagequeue.cc |
diff --git a/webrtc/rtc_base/messagequeue.cc b/webrtc/rtc_base/messagequeue.cc |
index c22cea70e92005cff2d48a67602e9e0d7ac4e82c..fac7609cbf23af709f53c7b061d626c4b0fd266b 100644 |
--- a/webrtc/rtc_base/messagequeue.cc |
+++ b/webrtc/rtc_base/messagequeue.cc |
@@ -23,26 +23,25 @@ namespace { |
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 @@ bool MessageQueueManager::IsInitialized() { |
return instance_ != nullptr; |
} |
-MessageQueueManager::MessageQueueManager() : locked_(false) {} |
+MessageQueueManager::MessageQueueManager() : processing_(0) {} |
MessageQueueManager::~MessageQueueManager() { |
} |
@@ -82,7 +81,9 @@ void MessageQueueManager::Add(MessageQueue *message_queue) { |
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 @@ void MessageQueueManager::RemoveInternal(MessageQueue *message_queue) { |
// 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 @@ void MessageQueueManager::Clear(MessageHandler *handler) { |
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 @@ void MessageQueueManager::ProcessAllMessageQueuesInternal() { |
}; |
{ |
- 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 |