Use function-local static variable for MessageQueueManager singleton.
Rely on C++11 thread-safe initialization on first call to MessageQueueManager::Instance(), in the same way as for ThreadManager::Instance(). Bug: None Change-Id: I26244f90c5d7f94a2454688297f55bf96617e78c Reviewed-on: https://webrtc-review.googlesource.com/97721 Commit-Queue: Niels Moller <nisse@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24625}
This commit is contained in:
@ -48,18 +48,9 @@ class RTC_SCOPED_LOCKABLE MarkProcessingCritScope {
|
|||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// MessageQueueManager
|
// MessageQueueManager
|
||||||
|
|
||||||
MessageQueueManager* MessageQueueManager::instance_ = nullptr;
|
|
||||||
|
|
||||||
MessageQueueManager* MessageQueueManager::Instance() {
|
MessageQueueManager* MessageQueueManager::Instance() {
|
||||||
// Note: This is not thread safe, but it is first called before threads are
|
static MessageQueueManager* const instance = new MessageQueueManager;
|
||||||
// spawned.
|
return instance;
|
||||||
if (!instance_)
|
|
||||||
instance_ = new MessageQueueManager;
|
|
||||||
return instance_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MessageQueueManager::IsInitialized() {
|
|
||||||
return instance_ != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueManager::MessageQueueManager() : processing_(0) {}
|
MessageQueueManager::MessageQueueManager() : processing_(0) {}
|
||||||
@ -77,18 +68,9 @@ void MessageQueueManager::AddInternal(MessageQueue* message_queue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueueManager::Remove(MessageQueue* message_queue) {
|
void MessageQueueManager::Remove(MessageQueue* message_queue) {
|
||||||
// If there isn't a message queue manager instance, then there isn't a queue
|
|
||||||
// to remove.
|
|
||||||
if (!instance_)
|
|
||||||
return;
|
|
||||||
return Instance()->RemoveInternal(message_queue);
|
return Instance()->RemoveInternal(message_queue);
|
||||||
}
|
}
|
||||||
void MessageQueueManager::RemoveInternal(MessageQueue* message_queue) {
|
void MessageQueueManager::RemoveInternal(MessageQueue* message_queue) {
|
||||||
// If this is the last MessageQueue, destroy the manager as well so that
|
|
||||||
// we don't leak this object at program shutdown. As mentioned above, this is
|
|
||||||
// not thread-safe, but this should only happen at program termination (when
|
|
||||||
// the ThreadManager is destroyed, and threads are no longer active).
|
|
||||||
bool destroy = false;
|
|
||||||
{
|
{
|
||||||
CritScope cs(&crit_);
|
CritScope cs(&crit_);
|
||||||
// Prevent changes while the list of message queues is processed.
|
// Prevent changes while the list of message queues is processed.
|
||||||
@ -99,19 +81,10 @@ void MessageQueueManager::RemoveInternal(MessageQueue* message_queue) {
|
|||||||
if (iter != message_queues_.end()) {
|
if (iter != message_queues_.end()) {
|
||||||
message_queues_.erase(iter);
|
message_queues_.erase(iter);
|
||||||
}
|
}
|
||||||
destroy = message_queues_.empty();
|
|
||||||
}
|
|
||||||
if (destroy) {
|
|
||||||
instance_ = nullptr;
|
|
||||||
delete this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueueManager::Clear(MessageHandler* handler) {
|
void MessageQueueManager::Clear(MessageHandler* handler) {
|
||||||
// If there isn't a message queue manager instance, then there aren't any
|
|
||||||
// queues to remove this handler from.
|
|
||||||
if (!instance_)
|
|
||||||
return;
|
|
||||||
return Instance()->ClearInternal(handler);
|
return Instance()->ClearInternal(handler);
|
||||||
}
|
}
|
||||||
void MessageQueueManager::ClearInternal(MessageHandler* handler) {
|
void MessageQueueManager::ClearInternal(MessageHandler* handler) {
|
||||||
@ -125,9 +98,6 @@ void MessageQueueManager::ClearInternal(MessageHandler* handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessageQueueManager::ProcessAllMessageQueuesForTesting() {
|
void MessageQueueManager::ProcessAllMessageQueuesForTesting() {
|
||||||
if (!instance_) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return Instance()->ProcessAllMessageQueuesInternal();
|
return Instance()->ProcessAllMessageQueuesInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +195,7 @@ void MessageQueue::DoDestroy() {
|
|||||||
// is going away.
|
// is going away.
|
||||||
SignalQueueDestroyed();
|
SignalQueueDestroyed();
|
||||||
MessageQueueManager::Remove(this);
|
MessageQueueManager::Remove(this);
|
||||||
Clear(nullptr);
|
ClearInternal(nullptr, MQID_ANY, nullptr);
|
||||||
|
|
||||||
if (ss_) {
|
if (ss_) {
|
||||||
ss_->SetMessageQueue(nullptr);
|
ss_->SetMessageQueue(nullptr);
|
||||||
@ -480,7 +450,12 @@ void MessageQueue::Clear(MessageHandler* phandler,
|
|||||||
uint32_t id,
|
uint32_t id,
|
||||||
MessageList* removed) {
|
MessageList* removed) {
|
||||||
CritScope cs(&crit_);
|
CritScope cs(&crit_);
|
||||||
|
ClearInternal(phandler, id, removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageQueue::ClearInternal(MessageHandler* phandler,
|
||||||
|
uint32_t id,
|
||||||
|
MessageList* removed) {
|
||||||
// Remove messages with phandler
|
// Remove messages with phandler
|
||||||
|
|
||||||
if (fPeekKeep_ && msgPeek_.Match(phandler, id)) {
|
if (fPeekKeep_ && msgPeek_.Match(phandler, id)) {
|
||||||
|
@ -43,12 +43,6 @@ class MessageQueueManager {
|
|||||||
static void Remove(MessageQueue* message_queue);
|
static void Remove(MessageQueue* message_queue);
|
||||||
static void Clear(MessageHandler* handler);
|
static void Clear(MessageHandler* handler);
|
||||||
|
|
||||||
// For testing purposes, we expose whether or not the MessageQueueManager
|
|
||||||
// instance has been initialized. It has no other use relative to the rest of
|
|
||||||
// the functions of this class, which auto-initialize the underlying
|
|
||||||
// MessageQueueManager instance when necessary.
|
|
||||||
static bool IsInitialized();
|
|
||||||
|
|
||||||
// TODO(nisse): Delete alias, as soon as downstream code is updated.
|
// TODO(nisse): Delete alias, as soon as downstream code is updated.
|
||||||
static void ProcessAllMessageQueues() { ProcessAllMessageQueuesForTesting(); }
|
static void ProcessAllMessageQueues() { ProcessAllMessageQueuesForTesting(); }
|
||||||
|
|
||||||
@ -68,7 +62,6 @@ class MessageQueueManager {
|
|||||||
void ClearInternal(MessageHandler* handler);
|
void ClearInternal(MessageHandler* handler);
|
||||||
void ProcessAllMessageQueuesInternal();
|
void ProcessAllMessageQueuesInternal();
|
||||||
|
|
||||||
static MessageQueueManager* instance_;
|
|
||||||
// This list contains all live MessageQueues.
|
// This list contains all live MessageQueues.
|
||||||
std::vector<MessageQueue*> message_queues_ RTC_GUARDED_BY(crit_);
|
std::vector<MessageQueue*> message_queues_ RTC_GUARDED_BY(crit_);
|
||||||
|
|
||||||
@ -305,9 +298,15 @@ class MessageQueue {
|
|||||||
// if false was passed as init_queue to the MessageQueue constructor.
|
// if false was passed as init_queue to the MessageQueue constructor.
|
||||||
void DoInit();
|
void DoInit();
|
||||||
|
|
||||||
// Perform cleanup, subclasses that override Clear must call this from the
|
// Does not take any lock. Must be called either while holding crit_, or by
|
||||||
// destructor.
|
// the destructor (by definition, the latter has exclusive access).
|
||||||
void DoDestroy();
|
void ClearInternal(MessageHandler* phandler,
|
||||||
|
uint32_t id,
|
||||||
|
MessageList* removed) RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_);
|
||||||
|
|
||||||
|
// Perform cleanup; subclasses must call this from the destructor,
|
||||||
|
// and are not expected to actually hold the lock.
|
||||||
|
void DoDestroy() RTC_EXCLUSIVE_LOCKS_REQUIRED(&crit_);
|
||||||
|
|
||||||
void WakeUpSocketServer();
|
void WakeUpSocketServer();
|
||||||
|
|
||||||
|
@ -134,22 +134,6 @@ struct UnwrapMainThreadScope {
|
|||||||
bool rewrap_;
|
bool rewrap_;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(MessageQueueManager, Clear) {
|
|
||||||
UnwrapMainThreadScope s;
|
|
||||||
if (MessageQueueManager::IsInitialized()) {
|
|
||||||
RTC_LOG(LS_INFO)
|
|
||||||
<< "Unable to run MessageQueueManager::Clear test, since the "
|
|
||||||
<< "MessageQueueManager was already initialized by some "
|
|
||||||
<< "other test in this run.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bool deleted = false;
|
|
||||||
DeletedMessageHandler* handler = new DeletedMessageHandler(&deleted);
|
|
||||||
delete handler;
|
|
||||||
EXPECT_TRUE(deleted);
|
|
||||||
EXPECT_FALSE(MessageQueueManager::IsInitialized());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that ProcessAllMessageQueues does its essential function; process
|
// Ensure that ProcessAllMessageQueues does its essential function; process
|
||||||
// all messages (both delayed and non delayed) up until the current time, on
|
// all messages (both delayed and non delayed) up until the current time, on
|
||||||
// all registered message queues.
|
// all registered message queues.
|
||||||
|
@ -482,7 +482,7 @@ void Thread::Clear(MessageHandler* phandler,
|
|||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue::Clear(phandler, id, removed);
|
ClearInternal(phandler, id, removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(WEBRTC_MAC)
|
#if !defined(WEBRTC_MAC)
|
||||||
|
Reference in New Issue
Block a user