diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 402c364744..4cdefd4837 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -751,6 +751,8 @@ rtc_library("dtmf_sender") { "../rtc_base:checks", "../rtc_base:rtc_base", "../rtc_base:threading", + "../rtc_base/task_utils:pending_task_safety_flag", + "../rtc_base/task_utils:to_queued_task", "../rtc_base/third_party/sigslot", ] absl_deps = [ diff --git a/pc/dtmf_sender.cc b/pc/dtmf_sender.cc index 10378028c8..5af05c8964 100644 --- a/pc/dtmf_sender.cc +++ b/pc/dtmf_sender.cc @@ -18,6 +18,7 @@ #include "rtc_base/checks.h" #include "rtc_base/logging.h" #include "rtc_base/ref_counted_object.h" +#include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/thread.h" namespace webrtc { @@ -86,19 +87,22 @@ DtmfSender::DtmfSender(rtc::Thread* signaling_thread, } DtmfSender::~DtmfSender() { + RTC_DCHECK_RUN_ON(signaling_thread_); StopSending(); } void DtmfSender::RegisterObserver(DtmfSenderObserverInterface* observer) { + RTC_DCHECK_RUN_ON(signaling_thread_); observer_ = observer; } void DtmfSender::UnregisterObserver() { + RTC_DCHECK_RUN_ON(signaling_thread_); observer_ = nullptr; } bool DtmfSender::CanInsertDtmf() { - RTC_DCHECK(signaling_thread_->IsCurrent()); + RTC_DCHECK_RUN_ON(signaling_thread_); if (!provider_) { return false; } @@ -109,7 +113,7 @@ bool DtmfSender::InsertDtmf(const std::string& tones, int duration, int inter_tone_gap, int comma_delay) { - RTC_DCHECK(signaling_thread_->IsCurrent()); + RTC_DCHECK_RUN_ON(signaling_thread_); if (duration > kDtmfMaxDurationMs || duration < kDtmfMinDurationMs || inter_tone_gap < kDtmfMinGapMs || comma_delay < kDtmfMinGapMs) { @@ -132,38 +136,49 @@ bool DtmfSender::InsertDtmf(const std::string& tones, duration_ = duration; inter_tone_gap_ = inter_tone_gap; comma_delay_ = comma_delay; - // Clear the previous queue. - dtmf_driver_.Clear(); - // Kick off a new DTMF task queue. + + // Cancel any remaining tasks for previous tones. + if (safety_flag_) { + safety_flag_->SetNotAlive(); + } + safety_flag_ = PendingTaskSafetyFlag::Create(); + // Kick off a new DTMF task. QueueInsertDtmf(RTC_FROM_HERE, 1 /*ms*/); return true; } std::string DtmfSender::tones() const { + RTC_DCHECK_RUN_ON(signaling_thread_); return tones_; } int DtmfSender::duration() const { + RTC_DCHECK_RUN_ON(signaling_thread_); return duration_; } int DtmfSender::inter_tone_gap() const { + RTC_DCHECK_RUN_ON(signaling_thread_); return inter_tone_gap_; } int DtmfSender::comma_delay() const { + RTC_DCHECK_RUN_ON(signaling_thread_); return comma_delay_; } void DtmfSender::QueueInsertDtmf(const rtc::Location& posted_from, uint32_t delay_ms) { - dtmf_driver_.AsyncInvokeDelayed( - posted_from, signaling_thread_, [this] { DoInsertDtmf(); }, delay_ms); + signaling_thread_->PostDelayedTask( + ToQueuedTask(safety_flag_, + [this] { + RTC_DCHECK_RUN_ON(signaling_thread_); + DoInsertDtmf(); + }), + delay_ms); } void DtmfSender::DoInsertDtmf() { - RTC_DCHECK(signaling_thread_->IsCurrent()); - // Get the first DTMF tone from the tone buffer. Unrecognized characters will // be ignored and skipped. size_t first_tone_pos = tones_.find_first_of(kDtmfValidTones); @@ -222,13 +237,17 @@ void DtmfSender::DoInsertDtmf() { } void DtmfSender::OnProviderDestroyed() { + RTC_DCHECK_RUN_ON(signaling_thread_); + RTC_LOG(LS_INFO) << "The Dtmf provider is deleted. Clear the sending queue."; StopSending(); provider_ = nullptr; } void DtmfSender::StopSending() { - dtmf_driver_.Clear(); + if (safety_flag_) { + safety_flag_->SetNotAlive(); + } } } // namespace webrtc diff --git a/pc/dtmf_sender.h b/pc/dtmf_sender.h index 46145e5f3c..5cf7b2eba1 100644 --- a/pc/dtmf_sender.h +++ b/pc/dtmf_sender.h @@ -18,10 +18,10 @@ #include "api/dtmf_sender_interface.h" #include "api/proxy.h" #include "api/scoped_refptr.h" -#include "rtc_base/async_invoker.h" #include "rtc_base/constructor_magic.h" #include "rtc_base/location.h" #include "rtc_base/ref_count.h" +#include "rtc_base/task_utils/pending_task_safety_flag.h" #include "rtc_base/third_party/sigslot/sigslot.h" #include "rtc_base/thread.h" @@ -75,25 +75,27 @@ class DtmfSender : public DtmfSenderInterface, public sigslot::has_slots<> { private: DtmfSender(); - void QueueInsertDtmf(const rtc::Location& posted_from, uint32_t delay_ms); + void QueueInsertDtmf(const rtc::Location& posted_from, uint32_t delay_ms) + RTC_RUN_ON(signaling_thread_); // The DTMF sending task. - void DoInsertDtmf(); + void DoInsertDtmf() RTC_RUN_ON(signaling_thread_); void OnProviderDestroyed(); - void StopSending(); + void StopSending() RTC_RUN_ON(signaling_thread_); - DtmfSenderObserverInterface* observer_; + DtmfSenderObserverInterface* observer_ RTC_GUARDED_BY(signaling_thread_); rtc::Thread* signaling_thread_; - DtmfProviderInterface* provider_; - std::string tones_; - int duration_; - int inter_tone_gap_; - int comma_delay_; - // Invoker for running delayed tasks which feed the DTMF provider one tone at - // a time. - rtc::AsyncInvoker dtmf_driver_; + DtmfProviderInterface* provider_ RTC_GUARDED_BY(signaling_thread_); + std::string tones_ RTC_GUARDED_BY(signaling_thread_); + int duration_ RTC_GUARDED_BY(signaling_thread_); + int inter_tone_gap_ RTC_GUARDED_BY(signaling_thread_); + int comma_delay_ RTC_GUARDED_BY(signaling_thread_); + + // For cancelling the tasks which feed the DTMF provider one tone at a time. + rtc::scoped_refptr safety_flag_ RTC_GUARDED_BY( + signaling_thread_) RTC_PT_GUARDED_BY(signaling_thread_) = nullptr; RTC_DISALLOW_COPY_AND_ASSIGN(DtmfSender); };