3 * Copyright 2004--2009, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "talk/base/signalthread.h"
30 #include "talk/base/common.h"
34 ///////////////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////////////
38 SignalThread::SignalThread()
39 : main_(Thread::Current()),
43 main_->SignalQueueDestroyed.connect(this,
44 &SignalThread::OnMainThreadDestroyed);
45 worker_.SetName("SignalThread", this);
48 SignalThread::~SignalThread() {
49 ASSERT(refcount_ == 0);
52 bool SignalThread::SetName(const std::string& name, const void* obj) {
54 ASSERT(main_->IsCurrent());
55 ASSERT(kInit == state_);
56 return worker_.SetName(name, obj);
59 bool SignalThread::SetPriority(ThreadPriority priority) {
61 ASSERT(main_->IsCurrent());
62 ASSERT(kInit == state_);
63 return worker_.SetPriority(priority);
66 void SignalThread::Start() {
68 ASSERT(main_->IsCurrent());
69 if (kInit == state_ || kComplete == state_) {
78 void SignalThread::Destroy(bool wait) {
80 ASSERT(main_->IsCurrent());
81 if ((kInit == state_) || (kComplete == state_)) {
83 } else if (kRunning == state_ || kReleasing == state_) {
85 // OnWorkStop() must follow Quit(), so that when the thread wakes up due to
86 // OWS(), ContinueWork() will return false.
90 // Release the thread's lock so that it can return from ::Run.
101 void SignalThread::Release() {
103 ASSERT(main_->IsCurrent());
104 if (kComplete == state_) {
106 } else if (kRunning == state_) {
109 // if (kInit == state_) use Destroy()
114 bool SignalThread::ContinueWork() {
116 ASSERT(worker_.IsCurrent());
117 return worker_.ProcessMessages(0);
120 void SignalThread::OnMessage(Message *msg) {
122 if (ST_MSG_WORKER_DONE == msg->message_id) {
123 ASSERT(main_->IsCurrent());
125 bool do_delete = false;
126 if (kRunning == state_) {
131 if (kStopping != state_) {
132 // Before signaling that the work is done, make sure that the worker
133 // thread actually is done. We got here because DoWork() finished and
134 // Run() posted the ST_MSG_WORKER_DONE message. This means the worker
135 // thread is about to go away anyway, but sometimes it doesn't actually
136 // finish before SignalWorkDone is processed, and for a reusable
137 // SignalThread this makes an assert in thread.cc fire.
139 // Calling Stop() on the worker ensures that the OS thread that underlies
140 // the worker will finish, and will be set to NULL, enabling us to call
143 SignalWorkDone(this);
151 void SignalThread::Run() {
156 main_->Post(this, ST_MSG_WORKER_DONE);
161 void SignalThread::OnMainThreadDestroyed() {
166 } // namespace talk_base