diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index fdb622bc32..3436bb3e06 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -805,6 +805,8 @@ rtc_library("rtc_base") { "crypt_string.h", "data_rate_limiter.cc", "data_rate_limiter.h", + "deprecated/signal_thread.cc", + "deprecated/signal_thread.h", "dscp.h", "file_rotating_stream.cc", "file_rotating_stream.h", @@ -857,7 +859,6 @@ rtc_library("rtc_base") { "rtc_certificate.h", "rtc_certificate_generator.cc", "rtc_certificate_generator.h", - "signal_thread.cc", "signal_thread.h", "sigslot_repeater.h", "socket.cc", @@ -1308,6 +1309,7 @@ if (rtc_include_tests) { "callback_unittest.cc", "crc32_unittest.cc", "data_rate_limiter_unittest.cc", + "deprecated/signal_thread_unittest.cc", "fake_clock_unittest.cc", "helpers_unittest.cc", "ip_address_unittest.cc", @@ -1320,7 +1322,6 @@ if (rtc_include_tests) { "rolling_accumulator_unittest.cc", "rtc_certificate_generator_unittest.cc", "rtc_certificate_unittest.cc", - "signal_thread_unittest.cc", "sigslot_tester_unittest.cc", "test_client_unittest.cc", "thread_unittest.cc", diff --git a/rtc_base/signal_thread.cc b/rtc_base/deprecated/signal_thread.cc similarity index 80% rename from rtc_base/signal_thread.cc rename to rtc_base/deprecated/signal_thread.cc index 8f0d597f03..96bdd65155 100644 --- a/rtc_base/signal_thread.cc +++ b/rtc_base/deprecated/signal_thread.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "rtc_base/signal_thread.h" +#include "rtc_base/deprecated/signal_thread.h" #include @@ -23,19 +23,20 @@ namespace rtc { // SignalThread /////////////////////////////////////////////////////////////////////////////// -SignalThread::SignalThread() +DEPRECATED_SignalThread::DEPRECATED_SignalThread() : main_(Thread::Current()), worker_(this), state_(kInit), refcount_(1) { - main_->SignalQueueDestroyed.connect(this, - &SignalThread::OnMainThreadDestroyed); + main_->SignalQueueDestroyed.connect( + this, &DEPRECATED_SignalThread::OnMainThreadDestroyed); worker_.SetName("SignalThread", this); } -SignalThread::~SignalThread() { +DEPRECATED_SignalThread::~DEPRECATED_SignalThread() { rtc::CritScope lock(&cs_); RTC_DCHECK(refcount_ == 0); } -bool SignalThread::SetName(const std::string& name, const void* obj) { +bool DEPRECATED_SignalThread::SetName(const std::string& name, + const void* obj) { EnterExit ee(this); RTC_DCHECK(!destroy_called_); RTC_DCHECK(main_->IsCurrent()); @@ -43,7 +44,7 @@ bool SignalThread::SetName(const std::string& name, const void* obj) { return worker_.SetName(name, obj); } -void SignalThread::Start() { +void DEPRECATED_SignalThread::Start() { EnterExit ee(this); RTC_DCHECK(!destroy_called_); RTC_DCHECK(main_->IsCurrent()); @@ -56,7 +57,7 @@ void SignalThread::Start() { } } -void SignalThread::Destroy(bool wait) { +void DEPRECATED_SignalThread::Destroy(bool wait) { EnterExit ee(this); // Sometimes the caller can't guarantee which thread will call Destroy, only // that it will be the last thing it does. @@ -83,7 +84,7 @@ void SignalThread::Destroy(bool wait) { } } -void SignalThread::Release() { +void DEPRECATED_SignalThread::Release() { EnterExit ee(this); RTC_DCHECK(!destroy_called_); RTC_DCHECK(main_->IsCurrent()); @@ -97,14 +98,14 @@ void SignalThread::Release() { } } -bool SignalThread::ContinueWork() { +bool DEPRECATED_SignalThread::ContinueWork() { EnterExit ee(this); RTC_DCHECK(!destroy_called_); RTC_DCHECK(worker_.IsCurrent()); return worker_.ProcessMessages(0); } -void SignalThread::OnMessage(Message* msg) { +void DEPRECATED_SignalThread::OnMessage(Message* msg) { EnterExit ee(this); if (ST_MSG_WORKER_DONE == msg->message_id) { RTC_DCHECK(main_->IsCurrent()); @@ -135,21 +136,21 @@ void SignalThread::OnMessage(Message* msg) { } } -SignalThread::Worker::Worker(SignalThread* parent) +DEPRECATED_SignalThread::Worker::Worker(DEPRECATED_SignalThread* parent) : Thread(std::make_unique(), /*do_init=*/false), parent_(parent) { DoInit(); } -SignalThread::Worker::~Worker() { +DEPRECATED_SignalThread::Worker::~Worker() { Stop(); } -void SignalThread::Worker::Run() { +void DEPRECATED_SignalThread::Worker::Run() { parent_->Run(); } -void SignalThread::Run() { +void DEPRECATED_SignalThread::Run() { DoWork(); { EnterExit ee(this); @@ -159,12 +160,12 @@ void SignalThread::Run() { } } -void SignalThread::OnMainThreadDestroyed() { +void DEPRECATED_SignalThread::OnMainThreadDestroyed() { EnterExit ee(this); main_ = nullptr; } -bool SignalThread::Worker::IsProcessingMessagesForTesting() { +bool DEPRECATED_SignalThread::Worker::IsProcessingMessagesForTesting() { return false; } diff --git a/rtc_base/deprecated/signal_thread.h b/rtc_base/deprecated/signal_thread.h new file mode 100644 index 0000000000..54f2ba48c2 --- /dev/null +++ b/rtc_base/deprecated/signal_thread.h @@ -0,0 +1,166 @@ +/* + * 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. + */ + +#ifndef RTC_BASE_DEPRECATED_SIGNAL_THREAD_H_ +#define RTC_BASE_DEPRECATED_SIGNAL_THREAD_H_ + +#include + +#include "rtc_base/checks.h" +#include "rtc_base/constructor_magic.h" +#include "rtc_base/critical_section.h" +#include "rtc_base/deprecation.h" +#include "rtc_base/message_handler.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "rtc_base/thread.h" +#include "rtc_base/thread_annotations.h" + +namespace rtc { + +/////////////////////////////////////////////////////////////////////////////// +// NOTE: this class has been deprecated. Do not use for new code. New code +// should use factilities exposed by api/task_queue/ instead. +// +// SignalThread - Base class for worker threads. The main thread should call +// Start() to begin work, and then follow one of these models: +// Normal: Wait for SignalWorkDone, and then call Release to destroy. +// Cancellation: Call Release(true), to abort the worker thread. +// Fire-and-forget: Call Release(false), which allows the thread to run to +// completion, and then self-destruct without further notification. +// Periodic tasks: Wait for SignalWorkDone, then eventually call Start() +// again to repeat the task. When the instance isn't needed anymore, +// call Release. DoWork, OnWorkStart and OnWorkStop are called again, +// on a new thread. +// The subclass should override DoWork() to perform the background task. By +// periodically calling ContinueWork(), it can check for cancellation. +// OnWorkStart and OnWorkDone can be overridden to do pre- or post-work +// tasks in the context of the main thread. +/////////////////////////////////////////////////////////////////////////////// + +class DEPRECATED_SignalThread : public sigslot::has_slots<>, + protected MessageHandler { + public: + DEPRECATED_SignalThread(); + + // Context: Main Thread. Call before Start to change the worker's name. + bool SetName(const std::string& name, const void* obj); + + // Context: Main Thread. Call to begin the worker thread. + void Start(); + + // Context: Main Thread. If the worker thread is not running, deletes the + // object immediately. Otherwise, asks the worker thread to abort processing, + // and schedules the object to be deleted once the worker exits. + // SignalWorkDone will not be signalled. If wait is true, does not return + // until the thread is deleted. + void Destroy(bool wait); + + // Context: Main Thread. If the worker thread is complete, deletes the + // object immediately. Otherwise, schedules the object to be deleted once + // the worker thread completes. SignalWorkDone will be signalled. + void Release(); + + // Context: Main Thread. Signalled when work is complete. + sigslot::signal1 SignalWorkDone; + + enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE }; + + protected: + ~DEPRECATED_SignalThread() override; + + Thread* worker() { return &worker_; } + + // Context: Main Thread. Subclass should override to do pre-work setup. + virtual void OnWorkStart() {} + + // Context: Worker Thread. Subclass should override to do work. + virtual void DoWork() = 0; + + // Context: Worker Thread. Subclass should call periodically to + // dispatch messages and determine if the thread should terminate. + bool ContinueWork(); + + // Context: Worker Thread. Subclass should override when extra work is + // needed to abort the worker thread. + virtual void OnWorkStop() {} + + // Context: Main Thread. Subclass should override to do post-work cleanup. + virtual void OnWorkDone() {} + + // Context: Any Thread. If subclass overrides, be sure to call the base + // implementation. Do not use (message_id < ST_MSG_FIRST_AVAILABLE) + void OnMessage(Message* msg) override; + + private: + enum State { + kInit, // Initialized, but not started + kRunning, // Started and doing work + kReleasing, // Same as running, but to be deleted when work is done + kComplete, // Work is done + kStopping, // Work is being interrupted + }; + + class Worker : public Thread { + public: + explicit Worker(DEPRECATED_SignalThread* parent); + ~Worker() override; + void Run() override; + bool IsProcessingMessagesForTesting() override; + + private: + DEPRECATED_SignalThread* parent_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Worker); + }; + + class RTC_SCOPED_LOCKABLE EnterExit { + public: + explicit EnterExit(DEPRECATED_SignalThread* t) + RTC_EXCLUSIVE_LOCK_FUNCTION(t->cs_) + : t_(t) { + t_->cs_.Enter(); + // If refcount_ is zero then the object has already been deleted and we + // will be double-deleting it in ~EnterExit()! (shouldn't happen) + RTC_DCHECK_NE(0, t_->refcount_); + ++t_->refcount_; + } + ~EnterExit() RTC_UNLOCK_FUNCTION() { + bool d = (0 == --t_->refcount_); + t_->cs_.Leave(); + if (d) + delete t_; + } + + private: + DEPRECATED_SignalThread* t_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EnterExit); + }; + + void Run(); + void OnMainThreadDestroyed(); + + Thread* main_; + Worker worker_; + CriticalSection cs_; + State state_ RTC_GUARDED_BY(cs_); + int refcount_ RTC_GUARDED_BY(cs_); + bool destroy_called_ RTC_GUARDED_BY(cs_) = false; + + RTC_DISALLOW_COPY_AND_ASSIGN(DEPRECATED_SignalThread); +}; + +typedef RTC_DEPRECATED DEPRECATED_SignalThread SignalThread; + +/////////////////////////////////////////////////////////////////////////////// + +} // namespace rtc + +#endif // RTC_BASE_DEPRECATED_SIGNAL_THREAD_H_ diff --git a/rtc_base/signal_thread_unittest.cc b/rtc_base/deprecated/signal_thread_unittest.cc similarity index 95% rename from rtc_base/signal_thread_unittest.cc rename to rtc_base/deprecated/signal_thread_unittest.cc index 14761865b8..c280e970be 100644 --- a/rtc_base/signal_thread_unittest.cc +++ b/rtc_base/deprecated/signal_thread_unittest.cc @@ -28,9 +28,9 @@ static const int kTimeout = 10000; class SignalThreadTest : public ::testing::Test, public sigslot::has_slots<> { public: - class SlowSignalThread : public SignalThread { + class SlowSignalThread : public DEPRECATED_SignalThread { public: - SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {} + explicit SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {} ~SlowSignalThread() override { EXPECT_EQ(harness_->main_thread_, Thread::Current()); @@ -70,7 +70,7 @@ class SignalThreadTest : public ::testing::Test, public sigslot::has_slots<> { RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread); }; - void OnWorkComplete(rtc::SignalThread* thread) { + void OnWorkComplete(rtc::DEPRECATED_SignalThread* thread) { SlowSignalThread* t = static_cast(thread); EXPECT_EQ(t->harness(), this); EXPECT_EQ(main_thread_, Thread::Current()); @@ -157,7 +157,7 @@ class OwnerThread : public Thread, public sigslot::has_slots<> { rtc::CritScope cs(&crit_); return has_run_; } - void OnWorkDone(SignalThread* /*signal_thread*/) { + void OnWorkDone(DEPRECATED_SignalThread* /*signal_thread*/) { FAIL() << " This shouldn't get called."; } diff --git a/rtc_base/signal_thread.h b/rtc_base/signal_thread.h index 9229ca1abb..b444d54994 100644 --- a/rtc_base/signal_thread.h +++ b/rtc_base/signal_thread.h @@ -1,5 +1,5 @@ /* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * Copyright 2020 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 @@ -11,148 +11,9 @@ #ifndef RTC_BASE_SIGNAL_THREAD_H_ #define RTC_BASE_SIGNAL_THREAD_H_ -#include - -#include "rtc_base/checks.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/critical_section.h" -#include "rtc_base/message_handler.h" -#include "rtc_base/third_party/sigslot/sigslot.h" -#include "rtc_base/thread.h" -#include "rtc_base/thread_annotations.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// SignalThread - Base class for worker threads. The main thread should call -// Start() to begin work, and then follow one of these models: -// Normal: Wait for SignalWorkDone, and then call Release to destroy. -// Cancellation: Call Release(true), to abort the worker thread. -// Fire-and-forget: Call Release(false), which allows the thread to run to -// completion, and then self-destruct without further notification. -// Periodic tasks: Wait for SignalWorkDone, then eventually call Start() -// again to repeat the task. When the instance isn't needed anymore, -// call Release. DoWork, OnWorkStart and OnWorkStop are called again, -// on a new thread. -// The subclass should override DoWork() to perform the background task. By -// periodically calling ContinueWork(), it can check for cancellation. -// OnWorkStart and OnWorkDone can be overridden to do pre- or post-work -// tasks in the context of the main thread. -/////////////////////////////////////////////////////////////////////////////// - -class SignalThread : public sigslot::has_slots<>, protected MessageHandler { - public: - SignalThread(); - - // Context: Main Thread. Call before Start to change the worker's name. - bool SetName(const std::string& name, const void* obj); - - // Context: Main Thread. Call to begin the worker thread. - void Start(); - - // Context: Main Thread. If the worker thread is not running, deletes the - // object immediately. Otherwise, asks the worker thread to abort processing, - // and schedules the object to be deleted once the worker exits. - // SignalWorkDone will not be signalled. If wait is true, does not return - // until the thread is deleted. - void Destroy(bool wait); - - // Context: Main Thread. If the worker thread is complete, deletes the - // object immediately. Otherwise, schedules the object to be deleted once - // the worker thread completes. SignalWorkDone will be signalled. - void Release(); - - // Context: Main Thread. Signalled when work is complete. - sigslot::signal1 SignalWorkDone; - - enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE }; - - protected: - ~SignalThread() override; - - Thread* worker() { return &worker_; } - - // Context: Main Thread. Subclass should override to do pre-work setup. - virtual void OnWorkStart() {} - - // Context: Worker Thread. Subclass should override to do work. - virtual void DoWork() = 0; - - // Context: Worker Thread. Subclass should call periodically to - // dispatch messages and determine if the thread should terminate. - bool ContinueWork(); - - // Context: Worker Thread. Subclass should override when extra work is - // needed to abort the worker thread. - virtual void OnWorkStop() {} - - // Context: Main Thread. Subclass should override to do post-work cleanup. - virtual void OnWorkDone() {} - - // Context: Any Thread. If subclass overrides, be sure to call the base - // implementation. Do not use (message_id < ST_MSG_FIRST_AVAILABLE) - void OnMessage(Message* msg) override; - - private: - enum State { - kInit, // Initialized, but not started - kRunning, // Started and doing work - kReleasing, // Same as running, but to be deleted when work is done - kComplete, // Work is done - kStopping, // Work is being interrupted - }; - - class Worker : public Thread { - public: - explicit Worker(SignalThread* parent); - ~Worker() override; - void Run() override; - bool IsProcessingMessagesForTesting() override; - - private: - SignalThread* parent_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Worker); - }; - - class RTC_SCOPED_LOCKABLE EnterExit { - public: - explicit EnterExit(SignalThread* t) RTC_EXCLUSIVE_LOCK_FUNCTION(t->cs_) - : t_(t) { - t_->cs_.Enter(); - // If refcount_ is zero then the object has already been deleted and we - // will be double-deleting it in ~EnterExit()! (shouldn't happen) - RTC_DCHECK_NE(0, t_->refcount_); - ++t_->refcount_; - } - ~EnterExit() RTC_UNLOCK_FUNCTION() { - bool d = (0 == --t_->refcount_); - t_->cs_.Leave(); - if (d) - delete t_; - } - - private: - SignalThread* t_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EnterExit); - }; - - void Run(); - void OnMainThreadDestroyed(); - - Thread* main_; - Worker worker_; - CriticalSection cs_; - State state_ RTC_GUARDED_BY(cs_); - int refcount_ RTC_GUARDED_BY(cs_); - bool destroy_called_ RTC_GUARDED_BY(cs_) = false; - - RTC_DISALLOW_COPY_AND_ASSIGN(SignalThread); -}; - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc +// The facilities in this file have been deprecated. Please do not use them +// in new code. New code should use factilities exposed by api/task_queue/ +// instead. +#include "rtc_base/deprecated/signal_thread.h" #endif // RTC_BASE_SIGNAL_THREAD_H_