summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/webrtc/rtc_base/signalthread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/webrtc/rtc_base/signalthread.cc')
-rw-r--r--third_party/libwebrtc/webrtc/rtc_base/signalthread.cc154
1 files changed, 154 insertions, 0 deletions
diff --git a/third_party/libwebrtc/webrtc/rtc_base/signalthread.cc b/third_party/libwebrtc/webrtc/rtc_base/signalthread.cc
new file mode 100644
index 0000000000..3856dac99e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/rtc_base/signalthread.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/signalthread.h"
+
+#include "rtc_base/checks.h"
+
+namespace rtc {
+
+///////////////////////////////////////////////////////////////////////////////
+// SignalThread
+///////////////////////////////////////////////////////////////////////////////
+
+SignalThread::SignalThread(bool use_socket_server)
+ : main_(Thread::Current()),
+ worker_(this, use_socket_server),
+ state_(kInit),
+ refcount_(1) {
+ main_->SignalQueueDestroyed.connect(this,
+ &SignalThread::OnMainThreadDestroyed);
+ worker_.SetName("SignalThread", this);
+}
+
+SignalThread::~SignalThread() {
+ RTC_DCHECK(refcount_ == 0);
+}
+
+bool SignalThread::SetName(const std::string& name, const void* obj) {
+ EnterExit ee(this);
+ RTC_DCHECK(main_->IsCurrent());
+ RTC_DCHECK(kInit == state_);
+ return worker_.SetName(name, obj);
+}
+
+void SignalThread::Start() {
+ EnterExit ee(this);
+ RTC_DCHECK(main_->IsCurrent());
+ if (kInit == state_ || kComplete == state_) {
+ state_ = kRunning;
+ OnWorkStart();
+ worker_.Start();
+ } else {
+ RTC_NOTREACHED();
+ }
+}
+
+void SignalThread::Destroy(bool wait) {
+ EnterExit ee(this);
+ RTC_DCHECK(main_->IsCurrent());
+ if ((kInit == state_) || (kComplete == state_)) {
+ refcount_--;
+ } else if (kRunning == state_ || kReleasing == state_) {
+ state_ = kStopping;
+ // OnWorkStop() must follow Quit(), so that when the thread wakes up due to
+ // OWS(), ContinueWork() will return false.
+ worker_.Quit();
+ OnWorkStop();
+ if (wait) {
+ // Release the thread's lock so that it can return from ::Run.
+ cs_.Leave();
+ worker_.Stop();
+ cs_.Enter();
+ refcount_--;
+ }
+ } else {
+ RTC_NOTREACHED();
+ }
+}
+
+void SignalThread::Release() {
+ EnterExit ee(this);
+ RTC_DCHECK(main_->IsCurrent());
+ if (kComplete == state_) {
+ refcount_--;
+ } else if (kRunning == state_) {
+ state_ = kReleasing;
+ } else {
+ // if (kInit == state_) use Destroy()
+ RTC_NOTREACHED();
+ }
+}
+
+bool SignalThread::ContinueWork() {
+ EnterExit ee(this);
+ RTC_DCHECK(worker_.IsCurrent());
+ return worker_.ProcessMessages(0);
+}
+
+void SignalThread::OnMessage(Message *msg) {
+ EnterExit ee(this);
+ if (ST_MSG_WORKER_DONE == msg->message_id) {
+ RTC_DCHECK(main_->IsCurrent());
+ OnWorkDone();
+ bool do_delete = false;
+ if (kRunning == state_) {
+ state_ = kComplete;
+ } else {
+ do_delete = true;
+ }
+ if (kStopping != state_) {
+ // Before signaling that the work is done, make sure that the worker
+ // thread actually is done. We got here because DoWork() finished and
+ // Run() posted the ST_MSG_WORKER_DONE message. This means the worker
+ // thread is about to go away anyway, but sometimes it doesn't actually
+ // finish before SignalWorkDone is processed, and for a reusable
+ // SignalThread this makes an assert in thread.cc fire.
+ //
+ // Calling Stop() on the worker ensures that the OS thread that underlies
+ // the worker will finish, and will be set to null, enabling us to call
+ // Start() again.
+ worker_.Stop();
+ SignalWorkDone(this);
+ }
+ if (do_delete) {
+ refcount_--;
+ }
+ }
+}
+
+SignalThread::Worker::~Worker() {
+ Stop();
+}
+
+void SignalThread::Worker::Run() {
+ parent_->Run();
+}
+
+void SignalThread::Run() {
+ DoWork();
+ {
+ EnterExit ee(this);
+ if (main_) {
+ main_->Post(RTC_FROM_HERE, this, ST_MSG_WORKER_DONE);
+ }
+ }
+}
+
+void SignalThread::OnMainThreadDestroyed() {
+ EnterExit ee(this);
+ main_ = nullptr;
+}
+
+bool SignalThread::Worker::IsProcessingMessages() {
+ return false;
+}
+
+} // namespace rtc