diff --git a/BUILD.gn b/BUILD.gn index 8d9a76bf84..c0b47d5d11 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -555,7 +555,6 @@ if (rtc_include_tests && !build_with_chromium) { "rtc_base:untyped_function_unittest", "rtc_base:weak_ptr_unittests", "rtc_base/experiments:experiments_unittests", - "rtc_base/synchronization:sequence_checker_unittests", "rtc_base/task_utils:pending_task_safety_flag_unittests", "rtc_base/task_utils:to_queued_task_unittests", "sdk:sdk_tests", diff --git a/api/BUILD.gn b/api/BUILD.gn index fd952ab74e..fba441198a 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -706,6 +706,16 @@ rtc_source_set("function_view") { deps = [ "../rtc_base:checks" ] } +rtc_source_set("sequence_checker") { + visibility = [ "*" ] + sources = [ "sequence_checker.h" ] + deps = [ + "../rtc_base:checks", + "../rtc_base:macromagic", + "../rtc_base/synchronization:sequence_checker_internal", + ] +} + if (rtc_include_tests) { if (rtc_enable_protobuf && !build_with_chromium) { rtc_library("audioproc_f_api") { @@ -1039,6 +1049,7 @@ if (rtc_include_tests) { "rtp_packet_infos_unittest.cc", "rtp_parameters_unittest.cc", "scoped_refptr_unittest.cc", + "sequence_checker_unittest.cc", "test/create_time_controller_unittest.cc", ] @@ -1052,11 +1063,13 @@ if (rtc_include_tests) { ":rtp_packet_info", ":rtp_parameters", ":scoped_refptr", + ":sequence_checker", ":time_controller", "../rtc_base:checks", "../rtc_base:gunit_helpers", "../rtc_base:rtc_base_approved", "../rtc_base:rtc_task_queue", + "../rtc_base:task_queue_for_test", "../rtc_base/task_utils:repeating_task", "../test:fileutils", "../test:test_support", diff --git a/api/DEPS b/api/DEPS index 21afca9987..ffa9e98f47 100644 --- a/api/DEPS +++ b/api/DEPS @@ -277,6 +277,11 @@ specific_include_rules = { "+rtc_base/ref_count.h", ], + "sequence_checker\.h": [ + "+rtc_base/synchronization/sequence_checker_internal.h", + "+rtc_base/thread_annotations.h", + ], + # .cc files in api/ should not be restricted in what they can #include, # so we re-add all the top-level directories here. (That's because .h # files leak their #includes to whoever's #including them, but .cc files diff --git a/api/sequence_checker.h b/api/sequence_checker.h new file mode 100644 index 0000000000..6b46128392 --- /dev/null +++ b/api/sequence_checker.h @@ -0,0 +1,116 @@ +/* + * Copyright 2019 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 API_SEQUENCE_CHECKER_H_ +#define API_SEQUENCE_CHECKER_H_ + +#include "rtc_base/checks.h" +#include "rtc_base/synchronization/sequence_checker_internal.h" +#include "rtc_base/thread_annotations.h" + +namespace webrtc { + +// SequenceChecker is a helper class used to help verify that some methods +// of a class are called on the same task queue or thread. A +// SequenceChecker is bound to a a task queue if the object is +// created on a task queue, or a thread otherwise. +// +// +// Example: +// class MyClass { +// public: +// void Foo() { +// RTC_DCHECK_RUN_ON(sequence_checker_); +// ... (do stuff) ... +// } +// +// private: +// SequenceChecker sequence_checker_; +// } +// +// In Release mode, IsCurrent will always return true. +class RTC_LOCKABLE SequenceChecker +#if RTC_DCHECK_IS_ON + : public webrtc_sequence_checker_internal::SequenceCheckerImpl { + using Impl = webrtc_sequence_checker_internal::SequenceCheckerImpl; +#else + : public webrtc_sequence_checker_internal::SequenceCheckerDoNothing { + using Impl = webrtc_sequence_checker_internal::SequenceCheckerDoNothing; +#endif + public: + // Returns true if sequence checker is attached to the current sequence. + bool IsCurrent() const { return Impl::IsCurrent(); } + // Detaches checker from sequence to which it is attached. Next attempt + // to do a check with this checker will result in attaching this checker + // to the sequence on which check was performed. + void Detach() { Impl::Detach(); } +}; + +} // namespace webrtc + +// RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate +// variables are accessed from same thread/task queue. +// Using tools designed to check mutexes, it checks at compile time everywhere +// variable is access, there is a run-time dcheck thread/task queue is correct. +// +// class SequenceCheckerExample { +// public: +// int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) { +// return var2_; +// } +// +// void CallMeFromPacer() { +// RTC_DCHECK_RUN_ON(&pacer_sequence_checker_) +// << "Should be called from pacer"; +// CalledFromPacer(); +// } +// +// private: +// int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_); +// SequenceChecker pacer_sequence_checker_; +// }; +// +// class TaskQueueExample { +// public: +// class Encoder { +// public: +// rtc::TaskQueueBase& Queue() { return encoder_queue_; } +// void Encode() { +// RTC_DCHECK_RUN_ON(&encoder_queue_); +// DoSomething(var_); +// } +// +// private: +// rtc::TaskQueueBase& encoder_queue_; +// Frame var_ RTC_GUARDED_BY(encoder_queue_); +// }; +// +// void Encode() { +// // Will fail at runtime when DCHECK is enabled: +// // encoder_->Encode(); +// // Will work: +// rtc::scoped_refptr encoder = encoder_; +// encoder_->Queue().PostTask([encoder] { encoder->Encode(); }); +// } +// +// private: +// rtc::scoped_refptr encoder_; +// } + +// Document if a function expected to be called from same thread/task queue. +#define RTC_RUN_ON(x) \ + RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x)) + +#define RTC_DCHECK_RUN_ON(x) \ + webrtc::webrtc_sequence_checker_internal::SequenceCheckerScope \ + seq_check_scope(x); \ + RTC_DCHECK((x)->IsCurrent()) \ + << webrtc::webrtc_sequence_checker_internal::ExpectationToString(x) + +#endif // API_SEQUENCE_CHECKER_H_ diff --git a/rtc_base/synchronization/sequence_checker_unittest.cc b/api/sequence_checker_unittest.cc similarity index 97% rename from rtc_base/synchronization/sequence_checker_unittest.cc rename to api/sequence_checker_unittest.cc index ff91b0a7fb..4029b8c9a0 100644 --- a/rtc_base/synchronization/sequence_checker_unittest.cc +++ b/api/sequence_checker_unittest.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "rtc_base/synchronization/sequence_checker.h" +#include "api/sequence_checker.h" #include #include @@ -16,7 +16,6 @@ #include "api/function_view.h" #include "rtc_base/event.h" #include "rtc_base/platform_thread.h" -#include "rtc_base/synchronization/sequence_checker.h" #include "rtc_base/task_queue_for_test.h" #include "test/gtest.h" diff --git a/rtc_base/synchronization/BUILD.gn b/rtc_base/synchronization/BUILD.gn index 29e46b4936..55c5fa8ab2 100644 --- a/rtc_base/synchronization/BUILD.gn +++ b/rtc_base/synchronization/BUILD.gn @@ -46,16 +46,11 @@ rtc_library("mutex") { rtc_source_set("sequence_checker") { sources = [ "sequence_checker.h" ] - deps = [ - ":sequence_checker_internal", - "..:checks", - "..:deprecation", - "..:macromagic", - ] + deps = [ "../../api:sequence_checker" ] } rtc_library("sequence_checker_internal") { - visibility = [ ":sequence_checker" ] + visibility = [ "../../api:sequence_checker" ] sources = [ "sequence_checker_internal.cc", "sequence_checker_internal.h", @@ -115,21 +110,4 @@ if (rtc_include_tests) { ] } } - - if (!build_with_chromium) { - rtc_library("sequence_checker_unittests") { - testonly = true - - sources = [ "sequence_checker_unittest.cc" ] - deps = [ - ":sequence_checker", - "..:checks", - "..:rtc_base_approved", - "..:task_queue_for_test", - "../../api:function_view", - "../../test:test_main", - "../../test:test_support", - ] - } - } } diff --git a/rtc_base/synchronization/sequence_checker.h b/rtc_base/synchronization/sequence_checker.h index abf0ebfcfa..52577bce72 100644 --- a/rtc_base/synchronization/sequence_checker.h +++ b/rtc_base/synchronization/sequence_checker.h @@ -7,115 +7,5 @@ * 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_SYNCHRONIZATION_SEQUENCE_CHECKER_H_ -#define RTC_BASE_SYNCHRONIZATION_SEQUENCE_CHECKER_H_ -#include - -#include "rtc_base/checks.h" -#include "rtc_base/deprecation.h" -#include "rtc_base/synchronization/sequence_checker_internal.h" -#include "rtc_base/thread_annotations.h" - -namespace webrtc { - -// SequenceChecker is a helper class used to help verify that some methods -// of a class are called on the same task queue or thread. A -// SequenceChecker is bound to a a task queue if the object is -// created on a task queue, or a thread otherwise. -// -// -// Example: -// class MyClass { -// public: -// void Foo() { -// RTC_DCHECK_RUN_ON(sequence_checker_); -// ... (do stuff) ... -// } -// -// private: -// SequenceChecker sequence_checker_; -// } -// -// In Release mode, IsCurrent will always return true. -#if RTC_DCHECK_IS_ON -class RTC_LOCKABLE SequenceChecker - : public webrtc_sequence_checker_internal::SequenceCheckerImpl {}; -#else -class RTC_LOCKABLE SequenceChecker - : public webrtc_sequence_checker_internal::SequenceCheckerDoNothing {}; -#endif // RTC_ENABLE_THREAD_CHECKER - -} // namespace webrtc - -// RTC_RUN_ON/RTC_GUARDED_BY/RTC_DCHECK_RUN_ON macros allows to annotate -// variables are accessed from same thread/task queue. -// Using tools designed to check mutexes, it checks at compile time everywhere -// variable is access, there is a run-time dcheck thread/task queue is correct. -// -// class ThreadExample { -// public: -// void NeedVar1() { -// RTC_DCHECK_RUN_ON(network_thread_); -// transport_->Send(); -// } -// -// private: -// rtc::Thread* network_thread_; -// int transport_ RTC_GUARDED_BY(network_thread_); -// }; -// -// class SequenceCheckerExample { -// public: -// int CalledFromPacer() RTC_RUN_ON(pacer_sequence_checker_) { -// return var2_; -// } -// -// void CallMeFromPacer() { -// RTC_DCHECK_RUN_ON(&pacer_sequence_checker_) -// << "Should be called from pacer"; -// CalledFromPacer(); -// } -// -// private: -// int pacer_var_ RTC_GUARDED_BY(pacer_sequence_checker_); -// SequenceChecker pacer_sequence_checker_; -// }; -// -// class TaskQueueExample { -// public: -// class Encoder { -// public: -// rtc::TaskQueue* Queue() { return encoder_queue_; } -// void Encode() { -// RTC_DCHECK_RUN_ON(encoder_queue_); -// DoSomething(var_); -// } -// -// private: -// rtc::TaskQueue* const encoder_queue_; -// Frame var_ RTC_GUARDED_BY(encoder_queue_); -// }; -// -// void Encode() { -// // Will fail at runtime when DCHECK is enabled: -// // encoder_->Encode(); -// // Will work: -// rtc::scoped_refptr encoder = encoder_; -// encoder_->Queue()->PostTask([encoder] { encoder->Encode(); }); -// } -// -// private: -// rtc::scoped_refptr encoder_; -// } - -// Document if a function expected to be called from same thread/task queue. -#define RTC_RUN_ON(x) \ - RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x)) - -#define RTC_DCHECK_RUN_ON(x) \ - webrtc::webrtc_sequence_checker_internal::SequenceCheckerScope scope(x); \ - RTC_DCHECK((x)->IsCurrent()) \ - << webrtc::webrtc_sequence_checker_internal::ExpectationToString(x) - -#endif // RTC_BASE_SYNCHRONIZATION_SEQUENCE_CHECKER_H_ +#include "api/sequence_checker.h"