Index: jingle/glue/thread_wrapper.cc |
diff --git a/jingle/glue/thread_wrapper.cc b/jingle/glue/thread_wrapper.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f61205306b566386fc625dce93d152e00908d430 |
--- /dev/null |
+++ b/jingle/glue/thread_wrapper.cc |
@@ -0,0 +1,198 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "jingle/glue/thread_wrapper.h" |
+ |
+namespace jingle_glue { |
+ |
+JingleThreadWrapper::JingleThreadWrapper(MessageLoop* message_loop) |
+ : message_loop_(message_loop) { |
+ DCHECK_EQ(message_loop_, MessageLoop::current()); |
+ |
+ talk_base::ThreadManager::SetCurrent(this); |
+ message_loop_->AddDestructionObserver(this); |
+} |
+ |
+JingleThreadWrapper::~JingleThreadWrapper() { |
+} |
+ |
+void JingleThreadWrapper::WillDestroyCurrentMessageLoop() { |
+ talk_base::ThreadManager::SetCurrent(NULL); |
+ message_loop_->RemoveDestructionObserver(this); |
+ delete this; |
+} |
+ |
+void JingleThreadWrapper::Post( |
+ talk_base::MessageHandler* handler, uint32 id, |
+ talk_base::MessageData* data, bool time_sensitive) { |
+ bool queue_was_empty; |
+ talk_base::Message message; |
+ message.phandler = handler; |
+ message.message_id = id; |
+ message.pdata = data; |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ queue_was_empty = messages_.empty(); |
+ messages_.push_back(message); |
+ } |
+ |
+ // Post new task only if there is the queue was empty. |
+ if (!queue_was_empty) { |
+ message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
+ this, &JingleThreadWrapper::RunPendingTasks)); |
+ } |
+} |
+ |
+void JingleThreadWrapper::PostDelayed( |
+ int delay_ms, talk_base::MessageHandler* handler, |
+ uint32 id, talk_base::MessageData* data) { |
+ talk_base::Message message; |
+ message.phandler = handler; |
+ message.message_id = id; |
+ message.pdata = data; |
+ talk_base::DelayedMessage delayed_message( |
+ delay_ms, talk_base::TimeAfter(delay_ms), dmsgq_next_num_++, message); |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ delayed_messages_.push_back(delayed_message); |
+ std::push_heap(delayed_messages_.begin(), delayed_messages_.end()); |
+ } |
+ |
+ message_loop_->PostDelayedTask( |
+ FROM_HERE, NewRunnableMethod(this, &JingleThreadWrapper::RunDelayedTask, |
+ delayed_message.msTrigger_), |
+ delay_ms); |
+} |
+ |
+void JingleThreadWrapper::Clear(talk_base::MessageHandler* handler, uint32 id, |
+ talk_base::MessageList* removed) { |
+ base::AutoLock auto_lock(lock_); |
+ |
+ for (std::list<talk_base::Message>::iterator it = messages_.begin(); |
Alpha Left Google
2011/03/26 01:06:01
These two loops look really similar, please add co
Sergey Ulanov
2011/03/26 01:44:24
Done.
|
+ it != messages_.end();) { |
+ if (it->Match(handler, id)) { |
+ if (removed) { |
+ removed->push_back(*it); |
+ } else { |
+ delete it->pdata; |
+ } |
+ it = messages_.erase(it); |
+ } else { |
+ ++it; |
+ } |
+ } |
+ |
+ for (DelayedMessagesHeap::iterator it = delayed_messages_.begin(); |
+ it != delayed_messages_.end();) { |
+ if (it->msg_.Match(handler, id)) { |
+ if (removed) { |
+ removed->push_back(it->msg_); |
+ } else { |
+ delete it->msg_.pdata; |
+ } |
+ // Move last element to the current position. |
+ *it = delayed_messages_.back(); |
+ delayed_messages_.erase(delayed_messages_.end() - 1); |
Alpha Left Google
2011/03/26 01:06:01
why not just use delayed_messages_.back()?
Sergey Ulanov
2011/03/26 01:44:24
erase() needs iterator. back() returns reference t
|
+ } else { |
+ ++it; |
+ } |
+ } |
+ |
+ // Sort the heap again after we've removed some messages. |
+ std::make_heap(delayed_messages_.begin(), delayed_messages_.end()); |
Alpha Left Google
2011/03/26 01:06:01
where is the comparator for messages, add comment
Sergey Ulanov
2011/03/26 01:44:24
It's defined in talk_base::DelayedMessage. Anyway
|
+} |
+ |
+void JingleThreadWrapper::RunPendingTasks() { |
+ bool have_message; |
+ |
+ do { |
+ have_message = false; |
+ talk_base::Message message; |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ if (!messages_.empty()) { |
+ have_message = true; |
+ message = messages_.front(); |
+ messages_.pop_front(); |
+ } |
+ } |
+ |
+ if (have_message) { |
+ message.phandler->OnMessage(&message); |
+ delete message.pdata; |
+ } |
+ } while (have_message); |
+} |
+ |
+void JingleThreadWrapper::RunDelayedTask(uint32 task_time) { |
+ bool have_message = false; |
+ talk_base::Message message; |
+ |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ if (!delayed_messages_.empty() && |
+ delayed_messages_.front().msTrigger_ == task_time) { |
+ have_message = true; |
+ message = delayed_messages_.front().msg_; |
+ std::pop_heap(delayed_messages_.begin(), delayed_messages_.end()); |
+ delayed_messages_.erase(delayed_messages_.end() - 1); |
Alpha Left Google
2011/03/26 01:06:01
why not use delayed_messages_.back()?
Sergey Ulanov
2011/03/26 01:44:24
back() returns reference to last element. erase()
|
+ } |
+ } |
+ |
+ if (have_message) { |
+ message.phandler->OnMessage(&message); |
+ delete message.pdata; |
+ } |
+} |
+ |
+void JingleThreadWrapper::Quit() { |
+ NOTREACHED(); |
Alpha Left Google
2011/03/26 01:06:01
These methods are NOTREACHED(), why? Explain pleas
Sergey Ulanov
2011/03/26 01:44:24
This is mentioned in the header. Added more commen
|
+} |
+ |
+bool JingleThreadWrapper::IsQuitting() { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+void JingleThreadWrapper::Restart() { |
+ NOTREACHED(); |
+} |
+ |
+bool JingleThreadWrapper::Get(talk_base::Message*, int, bool) { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+bool JingleThreadWrapper::Peek(talk_base::Message*, int) { |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+void JingleThreadWrapper::PostAt(uint32, talk_base::MessageHandler*, |
+ uint32, talk_base::MessageData*) { |
+ NOTREACHED(); |
+} |
+ |
+void JingleThreadWrapper::Dispatch(talk_base::Message* msg) { |
+ NOTREACHED(); |
+} |
+ |
+void JingleThreadWrapper::ReceiveSends() { |
+ NOTREACHED(); |
+} |
+ |
+int JingleThreadWrapper::GetDelay() { |
+ NOTREACHED(); |
+ return 0; |
+} |
+ |
+void JingleThreadWrapper::Stop() { |
+ NOTREACHED(); |
+} |
+ |
+void JingleThreadWrapper::Run() { |
+ NOTREACHED(); |
+} |
+ |
+} // namespace jingle_glue |