OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/base/signalthread.h" | |
12 | |
13 #include "webrtc/base/checks.h" | |
14 | |
15 namespace rtc { | |
16 | |
17 /////////////////////////////////////////////////////////////////////////////// | |
18 // SignalThread | |
19 /////////////////////////////////////////////////////////////////////////////// | |
20 | |
21 SignalThread::SignalThread(bool use_socket_server) | |
22 : main_(Thread::Current()), | |
23 worker_(this, use_socket_server), | |
24 state_(kInit), | |
25 refcount_(1) { | |
26 main_->SignalQueueDestroyed.connect(this, | |
27 &SignalThread::OnMainThreadDestroyed); | |
28 worker_.SetName("SignalThread", this); | |
29 } | |
30 | |
31 SignalThread::~SignalThread() { | |
32 RTC_DCHECK(refcount_ == 0); | |
33 } | |
34 | |
35 bool SignalThread::SetName(const std::string& name, const void* obj) { | |
36 EnterExit ee(this); | |
37 RTC_DCHECK(main_->IsCurrent()); | |
38 RTC_DCHECK(kInit == state_); | |
39 return worker_.SetName(name, obj); | |
40 } | |
41 | |
42 void SignalThread::Start() { | |
43 EnterExit ee(this); | |
44 RTC_DCHECK(main_->IsCurrent()); | |
45 if (kInit == state_ || kComplete == state_) { | |
46 state_ = kRunning; | |
47 OnWorkStart(); | |
48 worker_.Start(); | |
49 } else { | |
50 RTC_NOTREACHED(); | |
51 } | |
52 } | |
53 | |
54 void SignalThread::Destroy(bool wait) { | |
55 EnterExit ee(this); | |
56 RTC_DCHECK(main_->IsCurrent()); | |
57 if ((kInit == state_) || (kComplete == state_)) { | |
58 refcount_--; | |
59 } else if (kRunning == state_ || kReleasing == state_) { | |
60 state_ = kStopping; | |
61 // OnWorkStop() must follow Quit(), so that when the thread wakes up due to | |
62 // OWS(), ContinueWork() will return false. | |
63 worker_.Quit(); | |
64 OnWorkStop(); | |
65 if (wait) { | |
66 // Release the thread's lock so that it can return from ::Run. | |
67 cs_.Leave(); | |
68 worker_.Stop(); | |
69 cs_.Enter(); | |
70 refcount_--; | |
71 } | |
72 } else { | |
73 RTC_NOTREACHED(); | |
74 } | |
75 } | |
76 | |
77 void SignalThread::Release() { | |
78 EnterExit ee(this); | |
79 RTC_DCHECK(main_->IsCurrent()); | |
80 if (kComplete == state_) { | |
81 refcount_--; | |
82 } else if (kRunning == state_) { | |
83 state_ = kReleasing; | |
84 } else { | |
85 // if (kInit == state_) use Destroy() | |
86 RTC_NOTREACHED(); | |
87 } | |
88 } | |
89 | |
90 bool SignalThread::ContinueWork() { | |
91 EnterExit ee(this); | |
92 RTC_DCHECK(worker_.IsCurrent()); | |
93 return worker_.ProcessMessages(0); | |
94 } | |
95 | |
96 void SignalThread::OnMessage(Message *msg) { | |
97 EnterExit ee(this); | |
98 if (ST_MSG_WORKER_DONE == msg->message_id) { | |
99 RTC_DCHECK(main_->IsCurrent()); | |
100 OnWorkDone(); | |
101 bool do_delete = false; | |
102 if (kRunning == state_) { | |
103 state_ = kComplete; | |
104 } else { | |
105 do_delete = true; | |
106 } | |
107 if (kStopping != state_) { | |
108 // Before signaling that the work is done, make sure that the worker | |
109 // thread actually is done. We got here because DoWork() finished and | |
110 // Run() posted the ST_MSG_WORKER_DONE message. This means the worker | |
111 // thread is about to go away anyway, but sometimes it doesn't actually | |
112 // finish before SignalWorkDone is processed, and for a reusable | |
113 // SignalThread this makes an assert in thread.cc fire. | |
114 // | |
115 // Calling Stop() on the worker ensures that the OS thread that underlies | |
116 // the worker will finish, and will be set to null, enabling us to call | |
117 // Start() again. | |
118 worker_.Stop(); | |
119 SignalWorkDone(this); | |
120 } | |
121 if (do_delete) { | |
122 refcount_--; | |
123 } | |
124 } | |
125 } | |
126 | |
127 SignalThread::Worker::~Worker() { | |
128 Stop(); | |
129 } | |
130 | |
131 void SignalThread::Worker::Run() { | |
132 parent_->Run(); | |
133 } | |
134 | |
135 void SignalThread::Run() { | |
136 DoWork(); | |
137 { | |
138 EnterExit ee(this); | |
139 if (main_) { | |
140 main_->Post(RTC_FROM_HERE, this, ST_MSG_WORKER_DONE); | |
141 } | |
142 } | |
143 } | |
144 | |
145 void SignalThread::OnMainThreadDestroyed() { | |
146 EnterExit ee(this); | |
147 main_ = nullptr; | |
148 } | |
149 | |
150 bool SignalThread::Worker::IsProcessingMessages() { | |
151 return false; | |
152 } | |
153 | |
154 } // namespace rtc | |
OLD | NEW |