summaryrefslogtreecommitdiff
path: root/chromium/third_party/webrtc/rtc_base
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/webrtc/rtc_base')
-rw-r--r--chromium/third_party/webrtc/rtc_base/BUILD.gn58
-rw-r--r--chromium/third_party/webrtc/rtc_base/DEPS2
-rw-r--r--chromium/third_party/webrtc/rtc_base/async_invoker.h2
-rw-r--r--chromium/third_party/webrtc/rtc_base/bit_buffer_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/buffer.h4
-rw-r--r--chromium/third_party/webrtc/rtc_base/buffer_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/checks.h2
-rw-r--r--chromium/third_party/webrtc/rtc_base/checks_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/critical_section.cc16
-rw-r--r--chromium/third_party/webrtc/rtc_base/critical_section_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/deprecated/signal_thread.cc (renamed from chromium/third_party/webrtc/rtc_base/signal_thread.cc)46
-rw-r--r--chromium/third_party/webrtc/rtc_base/deprecated/signal_thread.h166
-rw-r--r--chromium/third_party/webrtc/rtc_base/deprecated/signal_thread_unittest.cc (renamed from chromium/third_party/webrtc/rtc_base/signal_thread_unittest.cc)8
-rw-r--r--chromium/third_party/webrtc/rtc_base/experiments/BUILD.gn30
-rw-r--r--chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.cc4
-rw-r--r--chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.h2
-rw-r--r--chromium/third_party/webrtc/rtc_base/fake_network.h3
-rw-r--r--chromium/third_party/webrtc/rtc_base/logging.cc21
-rw-r--r--chromium/third_party/webrtc/rtc_base/message_handler.cc13
-rw-r--r--chromium/third_party/webrtc/rtc_base/message_handler.h28
-rw-r--r--chromium/third_party/webrtc/rtc_base/net_helpers.cc62
-rw-r--r--chromium/third_party/webrtc/rtc_base/net_helpers.h36
-rw-r--r--chromium/third_party/webrtc/rtc_base/network.h2
-rw-r--r--chromium/third_party/webrtc/rtc_base/network/BUILD.gn6
-rw-r--r--chromium/third_party/webrtc/rtc_base/network_monitor.cc7
-rw-r--r--chromium/third_party/webrtc/rtc_base/null_socket_server_unittest.cc3
-rw-r--r--chromium/third_party/webrtc/rtc_base/openssl_adapter.h3
-rw-r--r--chromium/third_party/webrtc/rtc_base/openssl_adapter_unittest.cc40
-rw-r--r--chromium/third_party/webrtc/rtc_base/operations_chain_unittest.cc5
-rw-r--r--chromium/third_party/webrtc/rtc_base/physical_socket_server.cc22
-rw-r--r--chromium/third_party/webrtc/rtc_base/physical_socket_server.h23
-rw-r--r--chromium/third_party/webrtc/rtc_base/platform_thread_types.cc28
-rw-r--r--chromium/third_party/webrtc/rtc_base/rate_statistics.cc109
-rw-r--r--chromium/third_party/webrtc/rtc_base/rate_statistics.h26
-rw-r--r--chromium/third_party/webrtc/rtc_base/rtc_certificate_generator.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/signal_thread.h148
-rw-r--r--chromium/third_party/webrtc/rtc_base/socket_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/ssl_adapter_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/stream.h2
-rw-r--r--chromium/third_party/webrtc/rtc_base/strings/string_builder_unittest.cc12
-rw-r--r--chromium/third_party/webrtc/rtc_base/swap_queue_unittest.cc6
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/BUILD.gn58
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/DEPS11
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex.cc39
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex.h145
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex_abseil.h37
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex_benchmark.cc95
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex_critical_section.h54
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex_pthread.h53
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/mutex_unittest.cc206
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.cc47
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.h20
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker_unittest.cc9
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/yield.cc36
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/yield.h20
-rw-r--r--chromium/third_party/webrtc/rtc_base/synchronization/yield_policy_unittest.cc2
-rw-r--r--chromium/third_party/webrtc/rtc_base/system/BUILD.gn6
-rw-r--r--chromium/third_party/webrtc/rtc_base/task_utils/BUILD.gn5
-rw-r--r--chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.cc15
-rw-r--r--chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.h36
-rw-r--r--chromium/third_party/webrtc/rtc_base/task_utils/repeating_task_unittest.cc52
-rw-r--r--chromium/third_party/webrtc/rtc_base/thread.cc169
-rw-r--r--chromium/third_party/webrtc/rtc_base/thread.h30
-rw-r--r--chromium/third_party/webrtc/rtc_base/thread_unittest.cc21
-rw-r--r--chromium/third_party/webrtc/rtc_base/virtual_socket_server.h2
-rw-r--r--chromium/third_party/webrtc/rtc_base/virtual_socket_unittest.cc5
66 files changed, 1658 insertions, 474 deletions
diff --git a/chromium/third_party/webrtc/rtc_base/BUILD.gn b/chromium/third_party/webrtc/rtc_base/BUILD.gn
index a61ede4ac98..c62b3f6afe7 100644
--- a/chromium/third_party/webrtc/rtc_base/BUILD.gn
+++ b/chromium/third_party/webrtc/rtc_base/BUILD.gn
@@ -59,8 +59,8 @@ rtc_library("rtc_base_approved") {
"system:rtc_export",
"system:unused",
"third_party/base64",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
public_deps = [] # no-presubmit-check TODO(webrtc:8603)
sources = [
@@ -154,6 +154,7 @@ rtc_library("platform_thread_types") {
"platform_thread_types.cc",
"platform_thread_types.h",
]
+ deps = [ ":macromagic" ]
}
rtc_source_set("refcount") {
@@ -176,6 +177,7 @@ rtc_library("criticalsection") {
":checks",
":macromagic",
":platform_thread_types",
+ "synchronization:yield",
"system:rtc_export",
"system:unused",
]
@@ -187,6 +189,7 @@ rtc_library("platform_thread") {
":rtc_task_queue_libevent",
":rtc_task_queue_win",
":rtc_task_queue_stdlib",
+ "synchronization:mutex",
"synchronization:sequence_checker",
]
sources = [
@@ -201,8 +204,8 @@ rtc_library("platform_thread") {
":rtc_event",
":thread_checker",
":timeutils",
- "//third_party/abseil-cpp/absl/strings",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
rtc_library("rtc_event") {
@@ -225,8 +228,8 @@ rtc_library("rtc_event") {
":checks",
"synchronization:yield_policy",
"system:warn_current_thread_is_deadlocked",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
}
@@ -240,6 +243,9 @@ rtc_library("logging") {
":platform_thread_types",
":stringutils",
":timeutils",
+ "synchronization:mutex",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings",
@@ -301,6 +307,8 @@ rtc_library("checks") {
":safe_compare",
"system:inline",
"system:rtc_export",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/meta:type_traits",
"//third_party/abseil-cpp/absl/strings",
]
@@ -317,13 +325,13 @@ rtc_library("rate_limiter") {
deps = [
":rtc_base_approved",
"../system_wrappers",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_source_set("sanitizer") {
sources = [ "sanitizer.h" ]
- deps = [ "//third_party/abseil-cpp/absl/meta:type_traits" ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/meta:type_traits" ]
}
rtc_source_set("bounded_inline_vector") {
@@ -398,6 +406,8 @@ rtc_library("stringutils") {
":macromagic",
":safe_minmax",
"../api:array_view",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
@@ -433,8 +443,8 @@ rtc_library("rtc_task_queue") {
"../api/task_queue",
"system:rtc_export",
"task_utils:to_queued_task",
- "//third_party/abseil-cpp/absl/memory",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
}
rtc_source_set("rtc_operations_chain") {
@@ -469,6 +479,8 @@ if (rtc_enable_libevent) {
":safe_conversions",
":timeutils",
"../api/task_queue",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/container:inlined_vector",
"//third_party/abseil-cpp/absl/strings",
]
@@ -490,8 +502,8 @@ if (is_mac || is_ios) {
":logging",
"../api/task_queue",
"system:gcd_helpers",
- "//third_party/abseil-cpp/absl/strings",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
}
@@ -512,8 +524,8 @@ if (is_win) {
":safe_conversions",
":timeutils",
"../api/task_queue",
- "//third_party/abseil-cpp/absl/strings",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
}
@@ -532,8 +544,8 @@ rtc_library("rtc_task_queue_stdlib") {
":safe_conversions",
":timeutils",
"../api/task_queue",
- "//third_party/abseil-cpp/absl/strings",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
rtc_library("weak_ptr") {
@@ -576,6 +588,8 @@ rtc_library("rtc_numerics") {
"../api/units:data_rate",
"../api/units:time_delta",
"../api/units:timestamp",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/types:optional",
]
@@ -760,6 +774,7 @@ rtc_library("rtc_base") {
deps = [
":checks",
":deprecation",
+ ":rtc_task_queue",
":stringutils",
"../api:array_view",
"../api:function_view",
@@ -767,12 +782,16 @@ rtc_library("rtc_base") {
"../api/task_queue",
"../system_wrappers:field_trial",
"network:sent_packet",
+ "synchronization:sequence_checker",
"system:file_wrapper",
"system:inline",
"system:rtc_export",
+ "task_utils:pending_task_safety_flag",
"task_utils:to_queued_task",
"third_party/base64",
"third_party/sigslot",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
@@ -801,6 +820,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",
@@ -853,7 +874,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",
@@ -1000,8 +1020,8 @@ rtc_library("gunit_helpers") {
":rtc_base_tests_utils",
":stringutils",
"../test:test_support",
- "//third_party/abseil-cpp/absl/strings",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
rtc_library("testclient") {
@@ -1066,6 +1086,8 @@ rtc_library("rtc_base_tests_utils") {
"../api/units:timestamp",
"memory:fifo_buffer",
"third_party/sigslot",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/memory",
]
@@ -1087,8 +1109,8 @@ rtc_library("task_queue_for_test") {
"../api/task_queue",
"../api/task_queue:default_task_queue_factory",
"task_utils:to_queued_task",
- "//third_party/abseil-cpp/absl/strings",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
if (rtc_include_tests) {
@@ -1128,8 +1150,8 @@ if (rtc_include_tests) {
"../test:test_support",
"third_party/sigslot",
"//testing/gtest",
- "//third_party/abseil-cpp/absl/memory",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
if (is_win) {
sources += [ "win32_socket_server_unittest.cc" ]
}
@@ -1211,6 +1233,8 @@ if (rtc_include_tests) {
"task_utils:to_queued_task",
"third_party/base64",
"third_party/sigslot",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
]
@@ -1228,8 +1252,8 @@ if (rtc_include_tests) {
":task_queue_for_test",
"../test:test_main",
"../test:test_support",
- "//third_party/abseil-cpp/absl/memory",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
}
rtc_library("rtc_operations_chain_unittests") {
@@ -1279,8 +1303,8 @@ if (rtc_include_tests) {
":rtc_numerics",
"../test:test_main",
"../test:test_support",
- "//third_party/abseil-cpp/absl/algorithm:container",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ]
}
rtc_library("rtc_json_unittests") {
@@ -1304,6 +1328,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",
@@ -1316,7 +1341,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",
@@ -1356,6 +1380,8 @@ if (rtc_include_tests) {
"synchronization:synchronization_unittests",
"task_utils:to_queued_task",
"third_party/sigslot",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/algorithm:container",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
diff --git a/chromium/third_party/webrtc/rtc_base/DEPS b/chromium/third_party/webrtc/rtc_base/DEPS
index 679d06dfc89..c9f7dc5898e 100644
--- a/chromium/third_party/webrtc/rtc_base/DEPS
+++ b/chromium/third_party/webrtc/rtc_base/DEPS
@@ -1,8 +1,8 @@
include_rules = [
"+base/third_party/libevent",
"+json",
- "+third_party/jsoncpp",
"+system_wrappers",
+ "+third_party/jsoncpp",
]
specific_include_rules = {
diff --git a/chromium/third_party/webrtc/rtc_base/async_invoker.h b/chromium/third_party/webrtc/rtc_base/async_invoker.h
index f15955d811f..82cdb21a30f 100644
--- a/chromium/third_party/webrtc/rtc_base/async_invoker.h
+++ b/chromium/third_party/webrtc/rtc_base/async_invoker.h
@@ -87,7 +87,7 @@ namespace rtc {
// destruction. This can be done by starting each chain of invocations on the
// same thread on which it will be destroyed, or by using some other
// synchronization method.
-class AsyncInvoker : public MessageHandler {
+class AsyncInvoker : public MessageHandlerAutoCleanup {
public:
AsyncInvoker();
~AsyncInvoker() override;
diff --git a/chromium/third_party/webrtc/rtc_base/bit_buffer_unittest.cc b/chromium/third_party/webrtc/rtc_base/bit_buffer_unittest.cc
index b3521b4951e..441cd264959 100644
--- a/chromium/third_party/webrtc/rtc_base/bit_buffer_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/bit_buffer_unittest.cc
@@ -142,7 +142,7 @@ TEST(BitBufferTest, ReadBits) {
EXPECT_FALSE(buffer.ReadBits(&val, 1));
}
-TEST(BitBufferTest, SetOffsetValues) {
+TEST(BitBufferDeathTest, SetOffsetValues) {
uint8_t bytes[4] = {0};
BitBufferWriter buffer(bytes, 4);
diff --git a/chromium/third_party/webrtc/rtc_base/buffer.h b/chromium/third_party/webrtc/rtc_base/buffer.h
index 3048b9179f4..d1639e2f71b 100644
--- a/chromium/third_party/webrtc/rtc_base/buffer.h
+++ b/chromium/third_party/webrtc/rtc_base/buffer.h
@@ -370,7 +370,9 @@ class BufferT {
: capacity;
std::unique_ptr<T[]> new_data(new T[new_capacity]);
- std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T));
+ if (data_ != nullptr) {
+ std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T));
+ }
MaybeZeroCompleteBuffer();
data_ = std::move(new_data);
capacity_ = new_capacity;
diff --git a/chromium/third_party/webrtc/rtc_base/buffer_unittest.cc b/chromium/third_party/webrtc/rtc_base/buffer_unittest.cc
index 3e7396dd2c8..8beae43cf94 100644
--- a/chromium/third_party/webrtc/rtc_base/buffer_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/buffer_unittest.cc
@@ -447,7 +447,7 @@ TEST(BufferTest, TestStruct) {
EXPECT_EQ(kObsidian, buf[2].stone);
}
-TEST(BufferTest, DieOnUseAfterMove) {
+TEST(BufferDeathTest, DieOnUseAfterMove) {
Buffer buf(17);
Buffer buf2 = std::move(buf);
EXPECT_EQ(buf2.size(), 17u);
diff --git a/chromium/third_party/webrtc/rtc_base/checks.h b/chromium/third_party/webrtc/rtc_base/checks.h
index 2fde3f6640b..61c074ac822 100644
--- a/chromium/third_party/webrtc/rtc_base/checks.h
+++ b/chromium/third_party/webrtc/rtc_base/checks.h
@@ -69,7 +69,7 @@ RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg);
// the reason that it's better to terminate might simply be that the error
// handling code isn't in place yet; in production, the reason might be that
// the author of the code truly believes that x will always be true, but that
-// she recognizes that if she is wrong, abrupt and unpleasant process
+// they recognizes that if they are wrong, abrupt and unpleasant process
// termination is still better than carrying on with the assumption violated.
//
// RTC_CHECK always evaluates its argument, so it's OK for x to have side
diff --git a/chromium/third_party/webrtc/rtc_base/checks_unittest.cc b/chromium/third_party/webrtc/rtc_base/checks_unittest.cc
index e6e094e5975..91e04cf6a1c 100644
--- a/chromium/third_party/webrtc/rtc_base/checks_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/checks_unittest.cc
@@ -19,7 +19,7 @@ TEST(ChecksTest, ExpressionNotEvaluatedWhenCheckPassing) {
}
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
-TEST(ChecksTest, Checks) {
+TEST(ChecksDeathTest, Checks) {
#if RTC_CHECK_MSG_ENABLED
EXPECT_DEATH(FATAL() << "message",
"\n\n#\n"
diff --git a/chromium/third_party/webrtc/rtc_base/critical_section.cc b/chromium/third_party/webrtc/rtc_base/critical_section.cc
index 1969edefa50..c6b17ff1b22 100644
--- a/chromium/third_party/webrtc/rtc_base/critical_section.cc
+++ b/chromium/third_party/webrtc/rtc_base/critical_section.cc
@@ -15,6 +15,7 @@
#include "rtc_base/atomic_ops.h"
#include "rtc_base/checks.h"
#include "rtc_base/platform_thread_types.h"
+#include "rtc_base/synchronization/yield.h"
#include "rtc_base/system/unused.h"
// TODO(tommi): Split this file up to per-platform implementation files.
@@ -42,7 +43,7 @@ CriticalSection::CriticalSection() {
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
#if defined(WEBRTC_MAC)
pthread_mutexattr_setpolicy_np(&mutex_attribute,
- _PTHREAD_MUTEX_POLICY_FAIRSHARE);
+ _PTHREAD_MUTEX_POLICY_FIRSTFIT);
#endif
pthread_mutex_init(&mutex_, &mutex_attribute);
pthread_mutexattr_destroy(&mutex_attribute);
@@ -217,19 +218,8 @@ CritScope::~CritScope() {
}
void GlobalLock::Lock() {
-#if !defined(WEBRTC_WIN) && \
- (!defined(WEBRTC_MAC) || RTC_USE_NATIVE_MUTEX_ON_MAC)
- const struct timespec ts_null = {0};
-#endif
-
while (AtomicOps::CompareAndSwap(&lock_acquired_, 0, 1)) {
-#if defined(WEBRTC_WIN)
- ::Sleep(0);
-#elif defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
- sched_yield();
-#else
- nanosleep(&ts_null, nullptr);
-#endif
+ webrtc::YieldCurrentThread();
}
}
diff --git a/chromium/third_party/webrtc/rtc_base/critical_section_unittest.cc b/chromium/third_party/webrtc/rtc_base/critical_section_unittest.cc
index 16aefd27400..3fa48323762 100644
--- a/chromium/third_party/webrtc/rtc_base/critical_section_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/critical_section_unittest.cc
@@ -78,7 +78,7 @@ class CompareAndSwapVerifier {
int zero_count_;
};
-class RunnerBase : public MessageHandler {
+class RunnerBase : public MessageHandlerAutoCleanup {
public:
explicit RunnerBase(int value)
: threads_active_(0),
diff --git a/chromium/third_party/webrtc/rtc_base/signal_thread.cc b/chromium/third_party/webrtc/rtc_base/deprecated/signal_thread.cc
index e100fbe179e..96bdd65155a 100644
--- a/chromium/third_party/webrtc/rtc_base/signal_thread.cc
+++ b/chromium/third_party/webrtc/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 <memory>
@@ -23,26 +23,30 @@ 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());
RTC_DCHECK(kInit == state_);
return worker_.SetName(name, obj);
}
-void SignalThread::Start() {
+void DEPRECATED_SignalThread::Start() {
EnterExit ee(this);
+ RTC_DCHECK(!destroy_called_);
RTC_DCHECK(main_->IsCurrent());
if (kInit == state_ || kComplete == state_) {
state_ = kRunning;
@@ -53,9 +57,13 @@ void SignalThread::Start() {
}
}
-void SignalThread::Destroy(bool wait) {
+void DEPRECATED_SignalThread::Destroy(bool wait) {
EnterExit ee(this);
- RTC_DCHECK(main_->IsCurrent());
+ // Sometimes the caller can't guarantee which thread will call Destroy, only
+ // that it will be the last thing it does.
+ // RTC_DCHECK(main_->IsCurrent());
+ RTC_DCHECK(!destroy_called_);
+ destroy_called_ = true;
if ((kInit == state_) || (kComplete == state_)) {
refcount_--;
} else if (kRunning == state_ || kReleasing == state_) {
@@ -76,8 +84,9 @@ void SignalThread::Destroy(bool wait) {
}
}
-void SignalThread::Release() {
+void DEPRECATED_SignalThread::Release() {
EnterExit ee(this);
+ RTC_DCHECK(!destroy_called_);
RTC_DCHECK(main_->IsCurrent());
if (kComplete == state_) {
refcount_--;
@@ -89,13 +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());
@@ -126,21 +136,21 @@ void SignalThread::OnMessage(Message* msg) {
}
}
-SignalThread::Worker::Worker(SignalThread* parent)
+DEPRECATED_SignalThread::Worker::Worker(DEPRECATED_SignalThread* parent)
: Thread(std::make_unique<NullSocketServer>(), /*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);
@@ -150,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/chromium/third_party/webrtc/rtc_base/deprecated/signal_thread.h b/chromium/third_party/webrtc/rtc_base/deprecated/signal_thread.h
new file mode 100644
index 00000000000..e84d4ce5580
--- /dev/null
+++ b/chromium/third_party/webrtc/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 <string>
+
+#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 MessageHandlerAutoCleanup {
+ 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<DEPRECATED_SignalThread*> 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/chromium/third_party/webrtc/rtc_base/signal_thread_unittest.cc b/chromium/third_party/webrtc/rtc_base/deprecated/signal_thread_unittest.cc
index 14761865b8a..c280e970bef 100644
--- a/chromium/third_party/webrtc/rtc_base/signal_thread_unittest.cc
+++ b/chromium/third_party/webrtc/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<SlowSignalThread*>(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/chromium/third_party/webrtc/rtc_base/experiments/BUILD.gn b/chromium/third_party/webrtc/rtc_base/experiments/BUILD.gn
index bb3e0ce8ae5..282b5b92709 100644
--- a/chromium/third_party/webrtc/rtc_base/experiments/BUILD.gn
+++ b/chromium/third_party/webrtc/rtc_base/experiments/BUILD.gn
@@ -17,8 +17,8 @@ rtc_library("alr_experiment") {
"../:rtc_base_approved",
"../../api/transport:field_trial_based_config",
"../../api/transport:webrtc_key_value_config",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("field_trial_parser") {
@@ -40,6 +40,8 @@ rtc_library("field_trial_parser") {
"../../rtc_base:logging",
"../../rtc_base:safe_conversions",
"../../rtc_base:stringutils",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings:strings",
"//third_party/abseil-cpp/absl/types:optional",
@@ -57,8 +59,8 @@ rtc_library("quality_rampup_experiment") {
"../../api/transport:field_trial_based_config",
"../../api/transport:webrtc_key_value_config",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("quality_scaler_settings") {
@@ -72,8 +74,8 @@ rtc_library("quality_scaler_settings") {
"../../api/transport:field_trial_based_config",
"../../api/transport:webrtc_key_value_config",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("quality_scaling_experiment") {
@@ -85,8 +87,8 @@ rtc_library("quality_scaling_experiment") {
"../:rtc_base_approved",
"../../api/video_codecs:video_codecs_api",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("normalize_simulcast_size_experiment") {
@@ -97,8 +99,8 @@ rtc_library("normalize_simulcast_size_experiment") {
deps = [
"../:rtc_base_approved",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("balanced_degradation_settings") {
@@ -111,8 +113,8 @@ rtc_library("balanced_degradation_settings") {
"../:rtc_base_approved",
"../../api/video_codecs:video_codecs_api",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("cpu_speed_experiment") {
@@ -123,8 +125,8 @@ rtc_library("cpu_speed_experiment") {
deps = [
"../:rtc_base_approved",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("rtt_mult_experiment") {
@@ -135,8 +137,8 @@ rtc_library("rtt_mult_experiment") {
deps = [
"../:rtc_base_approved",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("jitter_upper_bound_experiment") {
@@ -147,8 +149,8 @@ rtc_library("jitter_upper_bound_experiment") {
deps = [
"../:rtc_base_approved",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("rate_control_settings") {
@@ -164,6 +166,8 @@ rtc_library("rate_control_settings") {
"../../api/units:data_size",
"../../api/video_codecs:video_codecs_api",
"../../system_wrappers:field_trial",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
@@ -178,8 +182,8 @@ rtc_library("keyframe_interval_settings_experiment") {
":field_trial_parser",
"../../api/transport:field_trial_based_config",
"../../api/transport:webrtc_key_value_config",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("stable_target_rate_experiment") {
@@ -192,8 +196,8 @@ rtc_library("stable_target_rate_experiment") {
":rate_control_settings",
"../../api/transport:field_trial_based_config",
"../../api/transport:webrtc_key_value_config",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
rtc_library("min_video_bitrate_experiment") {
@@ -208,8 +212,8 @@ rtc_library("min_video_bitrate_experiment") {
"../../rtc_base:checks",
"../../rtc_base:logging",
"../../system_wrappers:field_trial",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
if (rtc_include_tests) {
@@ -255,7 +259,7 @@ if (rtc_include_tests) {
"../../test:field_trial",
"../../test:test_main",
"../../test:test_support",
- "//third_party/abseil-cpp/absl/types:optional",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
}
diff --git a/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.cc b/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.cc
index caf7e623683..ee6675c924d 100644
--- a/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.cc
+++ b/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.cc
@@ -70,4 +70,8 @@ bool QualityRampupExperiment::BwHigh(int64_t now_ms,
return (now_ms - *start_ms_) >= min_duration_ms_.Value();
}
+bool QualityRampupExperiment::Enabled() const {
+ return min_pixels_ || min_duration_ms_ || max_bitrate_kbps_;
+}
+
} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.h b/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.h
index ff9d7d38e52..9d469011040 100644
--- a/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.h
+++ b/chromium/third_party/webrtc/rtc_base/experiments/quality_rampup_experiment.h
@@ -33,6 +33,8 @@ class QualityRampupExperiment final {
// (max_bitrate_factor_) above |max_bitrate_kbps_| for |min_duration_ms_|.
bool BwHigh(int64_t now_ms, uint32_t available_bw_kbps);
+ bool Enabled() const;
+
private:
explicit QualityRampupExperiment(
const WebRtcKeyValueConfig* const key_value_config);
diff --git a/chromium/third_party/webrtc/rtc_base/fake_network.h b/chromium/third_party/webrtc/rtc_base/fake_network.h
index 040b24205ef..8bd50b69f0e 100644
--- a/chromium/third_party/webrtc/rtc_base/fake_network.h
+++ b/chromium/third_party/webrtc/rtc_base/fake_network.h
@@ -31,7 +31,8 @@ const int kFakeIPv4NetworkPrefixLength = 24;
const int kFakeIPv6NetworkPrefixLength = 64;
// Fake network manager that allows us to manually specify the IPs to use.
-class FakeNetworkManager : public NetworkManagerBase, public MessageHandler {
+class FakeNetworkManager : public NetworkManagerBase,
+ public MessageHandlerAutoCleanup {
public:
FakeNetworkManager() {}
diff --git a/chromium/third_party/webrtc/rtc_base/logging.cc b/chromium/third_party/webrtc/rtc_base/logging.cc
index ff7369dd5c4..bd2afcc9dd1 100644
--- a/chromium/third_party/webrtc/rtc_base/logging.cc
+++ b/chromium/third_party/webrtc/rtc_base/logging.cc
@@ -47,6 +47,7 @@ static const int kMaxLogLineSize = 1024 - 60;
#include "rtc_base/string_encode.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"
+#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
#include "rtc_base/time_utils.h"
@@ -72,7 +73,9 @@ const char* FilenameFromPath(const char* file) {
}
// Global lock for log subsystem, only needed to serialize access to streams_.
-CriticalSection g_log_crit;
+// TODO(bugs.webrtc.org/11665): this is not currently constant initialized and
+// trivially destructible.
+webrtc::Mutex g_log_mutex_;
} // namespace
/////////////////////////////////////////////////////////////////////////////
@@ -85,7 +88,7 @@ bool LogMessage::log_to_stderr_ = true;
// Note: we explicitly do not clean this up, because of the uncertain ordering
// of destructors at program exit. Let the person who sets the stream trigger
// cleanup by setting to null, or let it leak (safe at program exit).
-ABSL_CONST_INIT LogSink* LogMessage::streams_ RTC_GUARDED_BY(g_log_crit) =
+ABSL_CONST_INIT LogSink* LogMessage::streams_ RTC_GUARDED_BY(g_log_mutex_) =
nullptr;
// Boolean options default to false (0)
@@ -193,7 +196,7 @@ LogMessage::~LogMessage() {
#endif
}
- CritScope cs(&g_log_crit);
+ webrtc::MutexLock lock(&g_log_mutex_);
for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
if (severity_ >= entry->min_severity_) {
#if defined(WEBRTC_ANDROID)
@@ -242,7 +245,7 @@ void LogMessage::LogTimestamps(bool on) {
void LogMessage::LogToDebug(LoggingSeverity min_sev) {
g_dbg_sev = min_sev;
- CritScope cs(&g_log_crit);
+ webrtc::MutexLock lock(&g_log_mutex_);
UpdateMinLogSeverity();
}
@@ -251,7 +254,7 @@ void LogMessage::SetLogToStderr(bool log_to_stderr) {
}
int LogMessage::GetLogToStream(LogSink* stream) {
- CritScope cs(&g_log_crit);
+ webrtc::MutexLock lock(&g_log_mutex_);
LoggingSeverity sev = LS_NONE;
for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
if (stream == nullptr || stream == entry) {
@@ -262,7 +265,7 @@ int LogMessage::GetLogToStream(LogSink* stream) {
}
void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
- CritScope cs(&g_log_crit);
+ webrtc::MutexLock lock(&g_log_mutex_);
stream->min_severity_ = min_sev;
stream->next_ = streams_;
streams_ = stream;
@@ -270,7 +273,7 @@ void LogMessage::AddLogToStream(LogSink* stream, LoggingSeverity min_sev) {
}
void LogMessage::RemoveLogToStream(LogSink* stream) {
- CritScope cs(&g_log_crit);
+ webrtc::MutexLock lock(&g_log_mutex_);
for (LogSink** entry = &streams_; *entry != nullptr;
entry = &(*entry)->next_) {
if (*entry == stream) {
@@ -331,7 +334,7 @@ void LogMessage::ConfigureLogging(const char* params) {
}
void LogMessage::UpdateMinLogSeverity()
- RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_crit) {
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(g_log_mutex_) {
LoggingSeverity min_sev = g_dbg_sev;
for (LogSink* entry = streams_; entry != nullptr; entry = entry->next_) {
min_sev = std::min(min_sev, entry->min_severity_);
@@ -439,7 +442,7 @@ bool LogMessage::IsNoop(LoggingSeverity severity) {
// TODO(tommi): We're grabbing this lock for every LogMessage instance that
// is going to be logged. This introduces unnecessary synchronization for
// a feature that's mostly used for testing.
- CritScope cs(&g_log_crit);
+ webrtc::MutexLock lock(&g_log_mutex_);
return streams_ == nullptr;
}
diff --git a/chromium/third_party/webrtc/rtc_base/message_handler.cc b/chromium/third_party/webrtc/rtc_base/message_handler.cc
index 18a06e241d3..42b4c50b8a3 100644
--- a/chromium/third_party/webrtc/rtc_base/message_handler.cc
+++ b/chromium/third_party/webrtc/rtc_base/message_handler.cc
@@ -15,7 +15,18 @@
namespace rtc {
MessageHandler::~MessageHandler() {
- ThreadManager::Clear(this);
+ if (auto_cleanup_) {
+ // Note that even though this clears currently pending messages for the
+ // message handler, it's still racy since it doesn't prevent threads that
+ // might be in the process of posting new messages with would-be dangling
+ // pointers.
+ // This is related to the design of Message having a raw pointer.
+ // We could consider whether it would be safer to require message handlers
+ // to be reference counted (as some are).
+ ThreadManager::Clear(this);
+ }
}
+MessageHandlerAutoCleanup::~MessageHandlerAutoCleanup() {}
+
} // namespace rtc
diff --git a/chromium/third_party/webrtc/rtc_base/message_handler.h b/chromium/third_party/webrtc/rtc_base/message_handler.h
index 85cb7854851..7b6e682e297 100644
--- a/chromium/third_party/webrtc/rtc_base/message_handler.h
+++ b/chromium/third_party/webrtc/rtc_base/message_handler.h
@@ -21,17 +21,41 @@ namespace rtc {
struct Message;
-// Messages get dispatched to a MessageHandler
+// MessageQueue/Thread Messages get dispatched to a MessageHandler via the
+// |OnMessage()| callback method.
+//
+// Note: Besides being an interface, the class can perform automatic cleanup
+// in the destructor.
+// TODO(bugs.webrtc.org/11908): The |auto_cleanup| parameter and associated
+// logic is a temporary step while changing the MessageHandler class to be
+// a pure virtual interface. The automatic cleanup step involves a number of
+// complex operations and as part of this interface, can easily go by unnoticed
+// and bundled into situations where it's not needed.
class RTC_EXPORT MessageHandler {
public:
virtual ~MessageHandler();
virtual void OnMessage(Message* msg) = 0;
protected:
- MessageHandler() {}
+ // TODO(bugs.webrtc.org/11908): The |auto_cleanup| parameter needs to have a
+ // backwards compatible default value while external code is being updated.
+ explicit MessageHandler(bool auto_cleanup = true)
+ : auto_cleanup_(auto_cleanup) {}
private:
RTC_DISALLOW_COPY_AND_ASSIGN(MessageHandler);
+ const bool auto_cleanup_;
+};
+
+class RTC_EXPORT MessageHandlerAutoCleanup : public MessageHandler {
+ public:
+ ~MessageHandlerAutoCleanup() override;
+
+ protected:
+ MessageHandlerAutoCleanup() : MessageHandler(true) {}
+
+ private:
+ RTC_DISALLOW_COPY_AND_ASSIGN(MessageHandlerAutoCleanup);
};
} // namespace rtc
diff --git a/chromium/third_party/webrtc/rtc_base/net_helpers.cc b/chromium/third_party/webrtc/rtc_base/net_helpers.cc
index 6ff3791738b..c6685e2a65c 100644
--- a/chromium/third_party/webrtc/rtc_base/net_helpers.cc
+++ b/chromium/third_party/webrtc/rtc_base/net_helpers.cc
@@ -10,8 +10,6 @@
#include "rtc_base/net_helpers.h"
-#include <memory>
-
#if defined(WEBRTC_WIN)
#include <ws2spi.h>
#include <ws2tcpip.h>
@@ -26,8 +24,11 @@
#endif
#endif // defined(WEBRTC_POSIX) && !defined(__native_client__)
+#include "api/task_queue/task_queue_base.h"
#include "rtc_base/logging.h"
#include "rtc_base/signal_thread.h"
+#include "rtc_base/task_queue.h"
+#include "rtc_base/task_utils/to_queued_task.h"
#include "rtc_base/third_party/sigslot/sigslot.h" // for signal_with_thread...
namespace rtc {
@@ -83,18 +84,35 @@ int ResolveHostname(const std::string& hostname,
#endif // !__native_client__
}
-// AsyncResolver
-AsyncResolver::AsyncResolver() : SignalThread(), error_(-1) {}
+AsyncResolver::AsyncResolver() : error_(-1) {}
-AsyncResolver::~AsyncResolver() = default;
+AsyncResolver::~AsyncResolver() {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+}
void AsyncResolver::Start(const SocketAddress& addr) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
addr_ = addr;
- // SignalThred Start will kickoff the resolve process.
- SignalThread::Start();
+ webrtc::TaskQueueBase* current_task_queue = webrtc::TaskQueueBase::Current();
+ popup_thread_ = Thread::Create();
+ popup_thread_->Start();
+ popup_thread_->PostTask(webrtc::ToQueuedTask(
+ [this, flag = safety_.flag(), addr, current_task_queue] {
+ std::vector<IPAddress> addresses;
+ int error =
+ ResolveHostname(addr.hostname().c_str(), addr.family(), &addresses);
+ current_task_queue->PostTask(webrtc::ToQueuedTask(
+ std::move(flag), [this, error, addresses = std::move(addresses)] {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ ResolveDone(std::move(addresses), error);
+ }));
+ }));
}
bool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
if (error_ != 0 || addresses_.empty())
return false;
@@ -109,20 +127,40 @@ bool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const {
}
int AsyncResolver::GetError() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
return error_;
}
void AsyncResolver::Destroy(bool wait) {
- SignalThread::Destroy(wait);
+ // Some callers have trouble guaranteeing that Destroy is called on the
+ // sequence guarded by |sequence_checker_|.
+ // RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ destroy_called_ = true;
+ MaybeSelfDestruct();
}
-void AsyncResolver::DoWork() {
- error_ =
- ResolveHostname(addr_.hostname().c_str(), addr_.family(), &addresses_);
+const std::vector<IPAddress>& AsyncResolver::addresses() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK(!destroy_called_);
+ return addresses_;
}
-void AsyncResolver::OnWorkDone() {
+void AsyncResolver::ResolveDone(std::vector<IPAddress> addresses, int error) {
+ addresses_ = addresses;
+ error_ = error;
+ recursion_check_ = true;
SignalDone(this);
+ MaybeSelfDestruct();
+}
+
+void AsyncResolver::MaybeSelfDestruct() {
+ if (!recursion_check_) {
+ delete this;
+ } else {
+ recursion_check_ = false;
+ }
}
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) {
diff --git a/chromium/third_party/webrtc/rtc_base/net_helpers.h b/chromium/third_party/webrtc/rtc_base/net_helpers.h
index 1e06940be74..c6aa4be5b20 100644
--- a/chromium/third_party/webrtc/rtc_base/net_helpers.h
+++ b/chromium/third_party/webrtc/rtc_base/net_helpers.h
@@ -21,16 +21,23 @@
#include "rtc_base/async_resolver_interface.h"
#include "rtc_base/ip_address.h"
-#include "rtc_base/signal_thread.h"
#include "rtc_base/socket_address.h"
+#include "rtc_base/synchronization/sequence_checker.h"
#include "rtc_base/system/rtc_export.h"
+#include "rtc_base/task_utils/pending_task_safety_flag.h"
+#include "rtc_base/thread.h"
+#include "rtc_base/thread_annotations.h"
namespace rtc {
// AsyncResolver will perform async DNS resolution, signaling the result on
// the SignalDone from AsyncResolverInterface when the operation completes.
-class RTC_EXPORT AsyncResolver : public SignalThread,
- public AsyncResolverInterface {
+//
+// This class is thread-compatible, and all methods and destruction needs to
+// happen from the same rtc::Thread, except for Destroy which is allowed to
+// happen on another context provided it's not happening concurrently to another
+// public API call, and is the last access to the object.
+class RTC_EXPORT AsyncResolver : public AsyncResolverInterface {
public:
AsyncResolver();
~AsyncResolver() override;
@@ -40,17 +47,22 @@ class RTC_EXPORT AsyncResolver : public SignalThread,
int GetError() const override;
void Destroy(bool wait) override;
- const std::vector<IPAddress>& addresses() const { return addresses_; }
- void set_error(int error) { error_ = error; }
-
- protected:
- void DoWork() override;
- void OnWorkDone() override;
+ const std::vector<IPAddress>& addresses() const;
private:
- SocketAddress addr_;
- std::vector<IPAddress> addresses_;
- int error_;
+ void ResolveDone(std::vector<IPAddress> addresses, int error)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(sequence_checker_);
+ void MaybeSelfDestruct();
+
+ SocketAddress addr_ RTC_GUARDED_BY(sequence_checker_);
+ std::vector<IPAddress> addresses_ RTC_GUARDED_BY(sequence_checker_);
+ int error_ RTC_GUARDED_BY(sequence_checker_);
+ webrtc::ScopedTaskSafety safety_ RTC_GUARDED_BY(sequence_checker_);
+ std::unique_ptr<Thread> popup_thread_ RTC_GUARDED_BY(sequence_checker_);
+ bool recursion_check_ =
+ false; // Protects against SignalDone calling into Destroy.
+ bool destroy_called_ = false;
+ webrtc::SequenceChecker sequence_checker_;
};
// rtc namespaced wrappers for inet_ntop and inet_pton so we can avoid
diff --git a/chromium/third_party/webrtc/rtc_base/network.h b/chromium/third_party/webrtc/rtc_base/network.h
index a67d2a23392..9cf04de590d 100644
--- a/chromium/third_party/webrtc/rtc_base/network.h
+++ b/chromium/third_party/webrtc/rtc_base/network.h
@@ -217,7 +217,7 @@ class RTC_EXPORT NetworkManagerBase : public NetworkManager {
// Basic implementation of the NetworkManager interface that gets list
// of networks using OS APIs.
class RTC_EXPORT BasicNetworkManager : public NetworkManagerBase,
- public MessageHandler,
+ public MessageHandlerAutoCleanup,
public sigslot::has_slots<> {
public:
BasicNetworkManager();
diff --git a/chromium/third_party/webrtc/rtc_base/network/BUILD.gn b/chromium/third_party/webrtc/rtc_base/network/BUILD.gn
index 1d06defb3bc..35ae3d45f73 100644
--- a/chromium/third_party/webrtc/rtc_base/network/BUILD.gn
+++ b/chromium/third_party/webrtc/rtc_base/network/BUILD.gn
@@ -13,8 +13,6 @@ rtc_library("sent_packet") {
"sent_packet.cc",
"sent_packet.h",
]
- deps = [
- "../system:rtc_export",
- "//third_party/abseil-cpp/absl/types:optional",
- ]
+ deps = [ "../system:rtc_export" ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
diff --git a/chromium/third_party/webrtc/rtc_base/network_monitor.cc b/chromium/third_party/webrtc/rtc_base/network_monitor.cc
index 4eb52901f3c..eb2bce9e2cc 100644
--- a/chromium/third_party/webrtc/rtc_base/network_monitor.cc
+++ b/chromium/third_party/webrtc/rtc_base/network_monitor.cc
@@ -30,8 +30,11 @@ NetworkMonitorInterface::NetworkMonitorInterface() {}
NetworkMonitorInterface::~NetworkMonitorInterface() {}
-NetworkMonitorBase::NetworkMonitorBase() : worker_thread_(Thread::Current()) {}
-NetworkMonitorBase::~NetworkMonitorBase() {}
+NetworkMonitorBase::NetworkMonitorBase()
+ : MessageHandler(false), worker_thread_(Thread::Current()) {}
+NetworkMonitorBase::~NetworkMonitorBase() {
+ worker_thread_->Clear(this);
+}
void NetworkMonitorBase::OnNetworksChanged() {
RTC_LOG(LS_VERBOSE) << "Network change is received at the network monitor";
diff --git a/chromium/third_party/webrtc/rtc_base/null_socket_server_unittest.cc b/chromium/third_party/webrtc/rtc_base/null_socket_server_unittest.cc
index 39c16313b16..a875d6c2846 100644
--- a/chromium/third_party/webrtc/rtc_base/null_socket_server_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/null_socket_server_unittest.cc
@@ -25,7 +25,8 @@ namespace rtc {
static const uint32_t kTimeout = 5000U;
-class NullSocketServerTest : public ::testing::Test, public MessageHandler {
+class NullSocketServerTest : public ::testing::Test,
+ public MessageHandlerAutoCleanup {
protected:
void OnMessage(Message* message) override { ss_.WakeUp(); }
diff --git a/chromium/third_party/webrtc/rtc_base/openssl_adapter.h b/chromium/third_party/webrtc/rtc_base/openssl_adapter.h
index 0e76836bafa..6f1f7dccabd 100644
--- a/chromium/third_party/webrtc/rtc_base/openssl_adapter.h
+++ b/chromium/third_party/webrtc/rtc_base/openssl_adapter.h
@@ -32,7 +32,8 @@
namespace rtc {
-class OpenSSLAdapter final : public SSLAdapter, public MessageHandler {
+class OpenSSLAdapter final : public SSLAdapter,
+ public MessageHandlerAutoCleanup {
public:
static bool InitializeSSL();
static bool CleanupSSL();
diff --git a/chromium/third_party/webrtc/rtc_base/openssl_adapter_unittest.cc b/chromium/third_party/webrtc/rtc_base/openssl_adapter_unittest.cc
index b161304d652..4bd87992d4d 100644
--- a/chromium/third_party/webrtc/rtc_base/openssl_adapter_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/openssl_adapter_unittest.cc
@@ -25,28 +25,34 @@ namespace {
class MockAsyncSocket : public AsyncSocket {
public:
virtual ~MockAsyncSocket() = default;
- MOCK_METHOD1(Accept, AsyncSocket*(SocketAddress*));
- MOCK_CONST_METHOD0(GetLocalAddress, SocketAddress());
- MOCK_CONST_METHOD0(GetRemoteAddress, SocketAddress());
- MOCK_METHOD1(Bind, int(const SocketAddress&));
- MOCK_METHOD1(Connect, int(const SocketAddress&));
- MOCK_METHOD2(Send, int(const void*, size_t));
- MOCK_METHOD3(SendTo, int(const void*, size_t, const SocketAddress&));
- MOCK_METHOD3(Recv, int(void*, size_t, int64_t*));
- MOCK_METHOD4(RecvFrom, int(void*, size_t, SocketAddress*, int64_t*));
- MOCK_METHOD1(Listen, int(int));
- MOCK_METHOD0(Close, int());
- MOCK_CONST_METHOD0(GetError, int());
- MOCK_METHOD1(SetError, void(int));
- MOCK_CONST_METHOD0(GetState, ConnState());
- MOCK_METHOD2(GetOption, int(Option, int*));
- MOCK_METHOD2(SetOption, int(Option, int));
+ MOCK_METHOD(AsyncSocket*, Accept, (SocketAddress*), (override));
+ MOCK_METHOD(SocketAddress, GetLocalAddress, (), (const, override));
+ MOCK_METHOD(SocketAddress, GetRemoteAddress, (), (const, override));
+ MOCK_METHOD(int, Bind, (const SocketAddress&), (override));
+ MOCK_METHOD(int, Connect, (const SocketAddress&), (override));
+ MOCK_METHOD(int, Send, (const void*, size_t), (override));
+ MOCK_METHOD(int,
+ SendTo,
+ (const void*, size_t, const SocketAddress&),
+ (override));
+ MOCK_METHOD(int, Recv, (void*, size_t, int64_t*), (override));
+ MOCK_METHOD(int,
+ RecvFrom,
+ (void*, size_t, SocketAddress*, int64_t*),
+ (override));
+ MOCK_METHOD(int, Listen, (int), (override));
+ MOCK_METHOD(int, Close, (), (override));
+ MOCK_METHOD(int, GetError, (), (const, override));
+ MOCK_METHOD(void, SetError, (int), (override));
+ MOCK_METHOD(ConnState, GetState, (), (const, override));
+ MOCK_METHOD(int, GetOption, (Option, int*), (override));
+ MOCK_METHOD(int, SetOption, (Option, int), (override));
};
class MockCertVerifier : public SSLCertificateVerifier {
public:
virtual ~MockCertVerifier() = default;
- MOCK_METHOD1(Verify, bool(const SSLCertificate&));
+ MOCK_METHOD(bool, Verify, (const SSLCertificate&), (override));
};
} // namespace
diff --git a/chromium/third_party/webrtc/rtc_base/operations_chain_unittest.cc b/chromium/third_party/webrtc/rtc_base/operations_chain_unittest.cc
index 968f94c060c..ed3c924998a 100644
--- a/chromium/third_party/webrtc/rtc_base/operations_chain_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/operations_chain_unittest.cc
@@ -369,14 +369,15 @@ TEST(OperationsChainTest, FunctorIsNotDestroyedWhileExecuting) {
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
-TEST(OperationsChainTest, OperationNotInvokingCallbackShouldCrash) {
+TEST(OperationsChainDeathTest, OperationNotInvokingCallbackShouldCrash) {
scoped_refptr<OperationsChain> operations_chain = OperationsChain::Create();
EXPECT_DEATH(
operations_chain->ChainOperation([](std::function<void()> callback) {}),
"");
}
-TEST(OperationsChainTest, OperationInvokingCallbackMultipleTimesShouldCrash) {
+TEST(OperationsChainDeathTest,
+ OperationInvokingCallbackMultipleTimesShouldCrash) {
scoped_refptr<OperationsChain> operations_chain = OperationsChain::Create();
EXPECT_DEATH(
operations_chain->ChainOperation([](std::function<void()> callback) {
diff --git a/chromium/third_party/webrtc/rtc_base/physical_socket_server.cc b/chromium/third_party/webrtc/rtc_base/physical_socket_server.cc
index cf65300b4ac..3a953316695 100644
--- a/chromium/third_party/webrtc/rtc_base/physical_socket_server.cc
+++ b/chromium/third_party/webrtc/rtc_base/physical_socket_server.cc
@@ -1365,12 +1365,6 @@ bool PhysicalSocketServer::WaitSelect(int cmsWait, bool process_io) {
#if defined(WEBRTC_USE_EPOLL)
-// Initial number of events to process with one call to "epoll_wait".
-static const size_t kInitialEpollEvents = 128;
-
-// Maximum number of events to process with one call to "epoll_wait".
-static const size_t kMaxEpollEvents = 8192;
-
void PhysicalSocketServer::AddEpoll(Dispatcher* pdispatcher) {
RTC_DCHECK(epoll_fd_ != INVALID_SOCKET);
int fd = pdispatcher->GetDescriptor();
@@ -1437,20 +1431,13 @@ bool PhysicalSocketServer::WaitEpoll(int cmsWait) {
tvStop = TimeAfter(cmsWait);
}
- if (epoll_events_.empty()) {
- // The initial space to receive events is created only if epoll is used.
- epoll_events_.resize(kInitialEpollEvents);
- }
-
fWait_ = true;
-
while (fWait_) {
// Wait then call handlers as appropriate
// < 0 means error
// 0 means timeout
// > 0 means count of descriptors ready
- int n = epoll_wait(epoll_fd_, &epoll_events_[0],
- static_cast<int>(epoll_events_.size()),
+ int n = epoll_wait(epoll_fd_, epoll_events_.data(), epoll_events_.size(),
static_cast<int>(tvWait));
if (n < 0) {
if (errno != EINTR) {
@@ -1483,13 +1470,6 @@ bool PhysicalSocketServer::WaitEpoll(int cmsWait) {
}
}
- if (static_cast<size_t>(n) == epoll_events_.size() &&
- epoll_events_.size() < kMaxEpollEvents) {
- // We used the complete space to receive events, increase size for future
- // iterations.
- epoll_events_.resize(std::max(epoll_events_.size() * 2, kMaxEpollEvents));
- }
-
if (cmsWait != kForever) {
tvWait = TimeDiff(tvStop, TimeMillis());
if (tvWait < 0) {
diff --git a/chromium/third_party/webrtc/rtc_base/physical_socket_server.h b/chromium/third_party/webrtc/rtc_base/physical_socket_server.h
index e7985db7db6..e21e53b8ecb 100644
--- a/chromium/third_party/webrtc/rtc_base/physical_socket_server.h
+++ b/chromium/third_party/webrtc/rtc_base/physical_socket_server.h
@@ -16,6 +16,7 @@
#define WEBRTC_USE_EPOLL 1
#endif
+#include <array>
#include <memory>
#include <set>
#include <vector>
@@ -24,6 +25,7 @@
#include "rtc_base/net_helpers.h"
#include "rtc_base/socket_server.h"
#include "rtc_base/system/rtc_export.h"
+#include "rtc_base/thread_annotations.h"
#if defined(WEBRTC_POSIX)
typedef int SOCKET;
@@ -80,9 +82,12 @@ class RTC_EXPORT PhysicalSocketServer : public SocketServer {
void Update(Dispatcher* dispatcher);
private:
+ // The number of events to process with one call to "epoll_wait".
+ static constexpr size_t kNumEpollEvents = 128;
+
typedef std::set<Dispatcher*> DispatcherSet;
- void AddRemovePendingDispatchers();
+ void AddRemovePendingDispatchers() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
#if defined(WEBRTC_POSIX)
bool WaitSelect(int cms, bool process_io);
@@ -94,14 +99,18 @@ class RTC_EXPORT PhysicalSocketServer : public SocketServer {
bool WaitEpoll(int cms);
bool WaitPoll(int cms, Dispatcher* dispatcher);
+ // This array is accessed in isolation by a thread calling into Wait().
+ // It's useless to use a SequenceChecker to guard it because a socket
+ // server can outlive the thread it's bound to, forcing the Wait call
+ // to have to reset the sequence checker on Wait calls.
+ std::array<epoll_event, kNumEpollEvents> epoll_events_;
const int epoll_fd_ = INVALID_SOCKET;
- std::vector<struct epoll_event> epoll_events_;
#endif // WEBRTC_USE_EPOLL
- DispatcherSet dispatchers_;
- DispatcherSet pending_add_dispatchers_;
- DispatcherSet pending_remove_dispatchers_;
- bool processing_dispatchers_ = false;
- Signaler* signal_wakeup_;
+ DispatcherSet dispatchers_ RTC_GUARDED_BY(crit_);
+ DispatcherSet pending_add_dispatchers_ RTC_GUARDED_BY(crit_);
+ DispatcherSet pending_remove_dispatchers_ RTC_GUARDED_BY(crit_);
+ bool processing_dispatchers_ RTC_GUARDED_BY(crit_) = false;
+ Signaler* signal_wakeup_; // Assigned in constructor only
CriticalSection crit_;
#if defined(WEBRTC_WIN)
const WSAEVENT socket_ev_;
diff --git a/chromium/third_party/webrtc/rtc_base/platform_thread_types.cc b/chromium/third_party/webrtc/rtc_base/platform_thread_types.cc
index ed4a2282624..b0243b41dc8 100644
--- a/chromium/third_party/webrtc/rtc_base/platform_thread_types.cc
+++ b/chromium/third_party/webrtc/rtc_base/platform_thread_types.cc
@@ -15,6 +15,16 @@
#include <sys/syscall.h>
#endif
+#if defined(WEBRTC_WIN)
+#include "rtc_base/arraysize.h"
+
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+// For compatibility with various versions of winuser and avoid clashing with
+// a potentially defined type, we use the RTC_ prefix.
+typedef HRESULT(WINAPI* RTC_SetThreadDescription)(HANDLE hThread,
+ PCWSTR lpThreadDescription);
+#endif
+
namespace rtc {
PlatformThreadId CurrentThreadId() {
@@ -58,6 +68,24 @@ bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
void SetCurrentThreadName(const char* name) {
#if defined(WEBRTC_WIN)
+ // The SetThreadDescription API works even if no debugger is attached.
+ // The names set with this API also show up in ETW traces. Very handy.
+ static auto set_thread_description_func =
+ reinterpret_cast<RTC_SetThreadDescription>(::GetProcAddress(
+ ::GetModuleHandleA("Kernel32.dll"), "SetThreadDescription"));
+ if (set_thread_description_func) {
+ // Convert from ASCII to UTF-16.
+ wchar_t wide_thread_name[64];
+ for (size_t i = 0; i < arraysize(wide_thread_name) - 1; ++i) {
+ wide_thread_name[i] = name[i];
+ if (wide_thread_name[i] == L'\0')
+ break;
+ }
+ // Guarantee null-termination.
+ wide_thread_name[arraysize(wide_thread_name) - 1] = L'\0';
+ set_thread_description_func(::GetCurrentThread(), wide_thread_name);
+ }
+
// For details see:
// https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
#pragma pack(push, 8)
diff --git a/chromium/third_party/webrtc/rtc_base/rate_statistics.cc b/chromium/third_party/webrtc/rtc_base/rate_statistics.cc
index c4c2e78581b..85621fa5555 100644
--- a/chromium/third_party/webrtc/rtc_base/rate_statistics.cc
+++ b/chromium/third_party/webrtc/rtc_base/rate_statistics.cc
@@ -20,29 +20,26 @@
namespace webrtc {
+RateStatistics::Bucket::Bucket(int64_t timestamp)
+ : sum(0), num_samples(0), timestamp(timestamp) {}
+
RateStatistics::RateStatistics(int64_t window_size_ms, float scale)
- : buckets_(new Bucket[window_size_ms]()),
- accumulated_count_(0),
+ : accumulated_count_(0),
+ first_timestamp_(-1),
num_samples_(0),
- oldest_time_(-window_size_ms),
- oldest_index_(0),
scale_(scale),
max_window_size_ms_(window_size_ms),
current_window_size_ms_(max_window_size_ms_) {}
RateStatistics::RateStatistics(const RateStatistics& other)
- : accumulated_count_(other.accumulated_count_),
+ : buckets_(other.buckets_),
+ accumulated_count_(other.accumulated_count_),
+ first_timestamp_(other.first_timestamp_),
overflow_(other.overflow_),
num_samples_(other.num_samples_),
- oldest_time_(other.oldest_time_),
- oldest_index_(other.oldest_index_),
scale_(other.scale_),
max_window_size_ms_(other.max_window_size_ms_),
- current_window_size_ms_(other.current_window_size_ms_) {
- buckets_ = std::make_unique<Bucket[]>(other.max_window_size_ms_);
- std::copy(other.buckets_.get(),
- other.buckets_.get() + other.max_window_size_ms_, buckets_.get());
-}
+ current_window_size_ms_(other.current_window_size_ms_) {}
RateStatistics::RateStatistics(RateStatistics&& other) = default;
@@ -52,33 +49,33 @@ void RateStatistics::Reset() {
accumulated_count_ = 0;
overflow_ = false;
num_samples_ = 0;
- oldest_time_ = -max_window_size_ms_;
- oldest_index_ = 0;
+ first_timestamp_ = -1;
current_window_size_ms_ = max_window_size_ms_;
- for (int64_t i = 0; i < max_window_size_ms_; i++)
- buckets_[i] = Bucket();
+ buckets_.clear();
}
void RateStatistics::Update(int64_t count, int64_t now_ms) {
- RTC_DCHECK_LE(0, count);
- if (now_ms < oldest_time_) {
- // Too old data is ignored.
- return;
- }
+ RTC_DCHECK_GE(count, 0);
EraseOld(now_ms);
+ if (first_timestamp_ == -1) {
+ first_timestamp_ = now_ms;
+ }
+
+ if (buckets_.empty() || now_ms != buckets_.back().timestamp) {
+ if (!buckets_.empty() && now_ms < buckets_.back().timestamp) {
+ RTC_LOG(LS_WARNING) << "Timestamp " << now_ms
+ << " is before the last added "
+ "timestamp in the rate window: "
+ << buckets_.back().timestamp << ", aligning to that.";
+ now_ms = buckets_.back().timestamp;
+ }
+ buckets_.emplace_back(now_ms);
+ }
+ Bucket& last_bucket = buckets_.back();
+ last_bucket.sum += count;
+ ++last_bucket.num_samples;
- // First ever sample, reset window to start now.
- if (!IsInitialized())
- oldest_time_ = now_ms;
-
- uint32_t now_offset = rtc::dchecked_cast<uint32_t>(now_ms - oldest_time_);
- RTC_DCHECK_LT(now_offset, max_window_size_ms_);
- uint32_t index = oldest_index_ + now_offset;
- if (index >= max_window_size_ms_)
- index -= max_window_size_ms_;
- buckets_[index].sum += count;
- ++buckets_[index].samples;
if (std::numeric_limits<int64_t>::max() - accumulated_count_ > count) {
accumulated_count_ += count;
} else {
@@ -92,10 +89,22 @@ absl::optional<int64_t> RateStatistics::Rate(int64_t now_ms) const {
// of the members as mutable...
const_cast<RateStatistics*>(this)->EraseOld(now_ms);
+ int active_window_size = 0;
+ if (first_timestamp_ != -1) {
+ if (first_timestamp_ <= now_ms - current_window_size_ms_) {
+ // Count window as full even if no data points currently in view, if the
+ // data stream started before the window.
+ active_window_size = current_window_size_ms_;
+ } else {
+ // Size of a single bucket is 1ms, so even if now_ms == first_timestmap_
+ // the window size should be 1.
+ active_window_size = now_ms - first_timestamp_ + 1;
+ }
+ }
+
// If window is a single bucket or there is only one sample in a data set that
// has not grown to the full window size, or if the accumulator has
// overflowed, treat this as rate unavailable.
- int active_window_size = now_ms - oldest_time_ + 1;
if (num_samples_ == 0 || active_window_size <= 1 ||
(num_samples_ <= 1 &&
rtc::SafeLt(active_window_size, current_window_size_ms_)) ||
@@ -114,43 +123,35 @@ absl::optional<int64_t> RateStatistics::Rate(int64_t now_ms) const {
}
void RateStatistics::EraseOld(int64_t now_ms) {
- if (!IsInitialized())
- return;
-
// New oldest time that is included in data set.
- int64_t new_oldest_time = now_ms - current_window_size_ms_ + 1;
-
- // New oldest time is older than the current one, no need to cull data.
- if (new_oldest_time <= oldest_time_)
- return;
+ const int64_t new_oldest_time = now_ms - current_window_size_ms_ + 1;
// Loop over buckets and remove too old data points.
- while (num_samples_ > 0 && oldest_time_ < new_oldest_time) {
- const Bucket& oldest_bucket = buckets_[oldest_index_];
+ while (!buckets_.empty() && buckets_.front().timestamp < new_oldest_time) {
+ const Bucket& oldest_bucket = buckets_.front();
RTC_DCHECK_GE(accumulated_count_, oldest_bucket.sum);
- RTC_DCHECK_GE(num_samples_, oldest_bucket.samples);
+ RTC_DCHECK_GE(num_samples_, oldest_bucket.num_samples);
accumulated_count_ -= oldest_bucket.sum;
- num_samples_ -= oldest_bucket.samples;
- buckets_[oldest_index_] = Bucket();
- if (++oldest_index_ >= max_window_size_ms_)
- oldest_index_ = 0;
- ++oldest_time_;
+ num_samples_ -= oldest_bucket.num_samples;
+ buckets_.pop_front();
// This does not clear overflow_ even when counter is empty.
// TODO(https://bugs.webrtc.org/11247): Consider if overflow_ can be reset.
}
- oldest_time_ = new_oldest_time;
}
bool RateStatistics::SetWindowSize(int64_t window_size_ms, int64_t now_ms) {
if (window_size_ms <= 0 || window_size_ms > max_window_size_ms_)
return false;
+ if (first_timestamp_ != -1) {
+ // If the window changes (e.g. decreases - removing data point, then
+ // increases again) we need to update the first timestamp mark as
+ // otherwise it indicates the window coveres a region of zeros, suddenly
+ // under-estimating the rate.
+ first_timestamp_ = std::max(first_timestamp_, now_ms - window_size_ms + 1);
+ }
current_window_size_ms_ = window_size_ms;
EraseOld(now_ms);
return true;
}
-bool RateStatistics::IsInitialized() const {
- return oldest_time_ != -max_window_size_ms_;
-}
-
} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/rate_statistics.h b/chromium/third_party/webrtc/rtc_base/rate_statistics.h
index 11c8cee7af2..dc8d7f5272a 100644
--- a/chromium/third_party/webrtc/rtc_base/rate_statistics.h
+++ b/chromium/third_party/webrtc/rtc_base/rate_statistics.h
@@ -14,6 +14,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <deque>
#include <memory>
#include "absl/types/optional.h"
@@ -28,6 +29,10 @@ namespace webrtc {
// high; for instance, a 20 Mbit/sec video stream can wrap a 32-bit byte
// counter in 14 minutes.
+// Note that timestamps used in Update(), Rate() and SetWindowSize() must never
+// decrease for two consecutive calls.
+// TODO(bugs.webrtc.org/11600): Migrate from int64_t to Timestamp.
+
class RTC_EXPORT RateStatistics {
public:
static constexpr float kBpsScale = 8000.0f;
@@ -65,19 +70,22 @@ class RTC_EXPORT RateStatistics {
private:
void EraseOld(int64_t now_ms);
- bool IsInitialized() const;
- // Counters are kept in buckets (circular buffer), with one bucket
- // per millisecond.
struct Bucket {
+ explicit Bucket(int64_t timestamp);
int64_t sum; // Sum of all samples in this bucket.
- int samples; // Number of samples in this bucket.
+ int num_samples; // Number of samples in this bucket.
+ const int64_t timestamp; // Timestamp this bucket corresponds to.
};
- std::unique_ptr<Bucket[]> buckets_;
+ // All buckets within the time window, ordered by time.
+ std::deque<Bucket> buckets_;
- // Total count recorded in buckets.
+ // Total count recorded in all buckets.
int64_t accumulated_count_;
+ // Timestamp of the first data point seen, or -1 of none seen.
+ int64_t first_timestamp_;
+
// True if accumulated_count_ has ever grown too large to be
// contained in its integer type.
bool overflow_ = false;
@@ -85,12 +93,6 @@ class RTC_EXPORT RateStatistics {
// The total number of samples in the buckets.
int num_samples_;
- // Oldest time recorded in buckets.
- int64_t oldest_time_;
-
- // Bucket index of oldest counter recorded in buckets.
- int64_t oldest_index_;
-
// To convert counts/ms to desired units
const float scale_;
diff --git a/chromium/third_party/webrtc/rtc_base/rtc_certificate_generator.cc b/chromium/third_party/webrtc/rtc_base/rtc_certificate_generator.cc
index 4c9d378dd2f..72f4277fa0c 100644
--- a/chromium/third_party/webrtc/rtc_base/rtc_certificate_generator.cc
+++ b/chromium/third_party/webrtc/rtc_base/rtc_certificate_generator.cc
@@ -40,7 +40,7 @@ enum {
// request. We are using a separate helper class so that a generation request
// can outlive the |RTCCertificateGenerator| that spawned it.
class RTCCertificateGenerationTask : public RefCountInterface,
- public MessageHandler {
+ public MessageHandlerAutoCleanup {
public:
RTCCertificateGenerationTask(
Thread* signaling_thread,
diff --git a/chromium/third_party/webrtc/rtc_base/signal_thread.h b/chromium/third_party/webrtc/rtc_base/signal_thread.h
index d9e8ade9b0e..b444d549949 100644
--- a/chromium/third_party/webrtc/rtc_base/signal_thread.h
+++ b/chromium/third_party/webrtc/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,147 +11,9 @@
#ifndef RTC_BASE_SIGNAL_THREAD_H_
#define RTC_BASE_SIGNAL_THREAD_H_
-#include <string>
-
-#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<SignalThread*> 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_;
- int refcount_;
-
- 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_
diff --git a/chromium/third_party/webrtc/rtc_base/socket_unittest.cc b/chromium/third_party/webrtc/rtc_base/socket_unittest.cc
index 6ea4b47bd1d..04024fb184b 100644
--- a/chromium/third_party/webrtc/rtc_base/socket_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/socket_unittest.cc
@@ -651,7 +651,7 @@ void SocketTest::CloseInClosedCallbackInternal(const IPAddress& loopback) {
EXPECT_TRUE(Socket::CS_CLOSED == client->GetState());
}
-class Sleeper : public MessageHandler {
+class Sleeper : public MessageHandlerAutoCleanup {
public:
void OnMessage(Message* msg) override { Thread::Current()->SleepMs(500); }
};
diff --git a/chromium/third_party/webrtc/rtc_base/ssl_adapter_unittest.cc b/chromium/third_party/webrtc/rtc_base/ssl_adapter_unittest.cc
index 125b4bd50d0..498eba312bc 100644
--- a/chromium/third_party/webrtc/rtc_base/ssl_adapter_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/ssl_adapter_unittest.cc
@@ -50,7 +50,7 @@ static std::string GetSSLProtocolName(const rtc::SSLMode& ssl_mode) {
class MockCertVerifier : public rtc::SSLCertificateVerifier {
public:
virtual ~MockCertVerifier() = default;
- MOCK_METHOD1(Verify, bool(const rtc::SSLCertificate&));
+ MOCK_METHOD(bool, Verify, (const rtc::SSLCertificate&), (override));
};
// TODO(benwright) - Move to using INSTANTIATE_TEST_SUITE_P instead of using
diff --git a/chromium/third_party/webrtc/rtc_base/stream.h b/chromium/third_party/webrtc/rtc_base/stream.h
index bfb9dc2c41e..036c5ad8c74 100644
--- a/chromium/third_party/webrtc/rtc_base/stream.h
+++ b/chromium/third_party/webrtc/rtc_base/stream.h
@@ -54,7 +54,7 @@ struct StreamEventData : public MessageData {
StreamEventData(int ev, int er) : events(ev), error(er) {}
};
-class RTC_EXPORT StreamInterface : public MessageHandler {
+class RTC_EXPORT StreamInterface : public MessageHandlerAutoCleanup {
public:
enum { MSG_POST_EVENT = 0xF1F1, MSG_MAX = MSG_POST_EVENT };
diff --git a/chromium/third_party/webrtc/rtc_base/strings/string_builder_unittest.cc b/chromium/third_party/webrtc/rtc_base/strings/string_builder_unittest.cc
index 84717ad1d10..99dfd862923 100644
--- a/chromium/third_party/webrtc/rtc_base/strings/string_builder_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/strings/string_builder_unittest.cc
@@ -59,7 +59,7 @@ TEST(SimpleStringBuilder, StdString) {
// off.
#if (GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)) || !RTC_DCHECK_IS_ON
-TEST(SimpleStringBuilder, BufferOverrunConstCharP) {
+TEST(SimpleStringBuilderDeathTest, BufferOverrunConstCharP) {
char sb_buf[4];
SimpleStringBuilder sb(sb_buf);
const char* const msg = "This is just too much";
@@ -71,7 +71,7 @@ TEST(SimpleStringBuilder, BufferOverrunConstCharP) {
#endif
}
-TEST(SimpleStringBuilder, BufferOverrunStdString) {
+TEST(SimpleStringBuilderDeathTest, BufferOverrunStdString) {
char sb_buf[4];
SimpleStringBuilder sb(sb_buf);
sb << 12;
@@ -84,7 +84,7 @@ TEST(SimpleStringBuilder, BufferOverrunStdString) {
#endif
}
-TEST(SimpleStringBuilder, BufferOverrunInt) {
+TEST(SimpleStringBuilderDeathTest, BufferOverrunInt) {
char sb_buf[4];
SimpleStringBuilder sb(sb_buf);
constexpr int num = -12345;
@@ -100,7 +100,7 @@ TEST(SimpleStringBuilder, BufferOverrunInt) {
#endif
}
-TEST(SimpleStringBuilder, BufferOverrunDouble) {
+TEST(SimpleStringBuilderDeathTest, BufferOverrunDouble) {
char sb_buf[5];
SimpleStringBuilder sb(sb_buf);
constexpr double num = 123.456;
@@ -113,7 +113,7 @@ TEST(SimpleStringBuilder, BufferOverrunDouble) {
#endif
}
-TEST(SimpleStringBuilder, BufferOverrunConstCharPAlreadyFull) {
+TEST(SimpleStringBuilderDeathTest, BufferOverrunConstCharPAlreadyFull) {
char sb_buf[4];
SimpleStringBuilder sb(sb_buf);
sb << 123;
@@ -126,7 +126,7 @@ TEST(SimpleStringBuilder, BufferOverrunConstCharPAlreadyFull) {
#endif
}
-TEST(SimpleStringBuilder, BufferOverrunIntAlreadyFull) {
+TEST(SimpleStringBuilderDeathTest, BufferOverrunIntAlreadyFull) {
char sb_buf[4];
SimpleStringBuilder sb(sb_buf);
sb << "xyz";
diff --git a/chromium/third_party/webrtc/rtc_base/swap_queue_unittest.cc b/chromium/third_party/webrtc/rtc_base/swap_queue_unittest.cc
index 199ac6b1854..3862d850fa4 100644
--- a/chromium/third_party/webrtc/rtc_base/swap_queue_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/swap_queue_unittest.cc
@@ -135,7 +135,7 @@ TEST(SwapQueueTest, SuccessfulItemVerifyFunctor) {
}
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
-TEST(SwapQueueTest, UnsuccessfulItemVerifyFunctor) {
+TEST(SwapQueueDeathTest, UnsuccessfulItemVerifyFunctor) {
// Queue item verifier for the test.
auto minus_2_verifier = [](const int& i) { return i > -2; };
SwapQueue<int, decltype(minus_2_verifier)> queue(2, minus_2_verifier);
@@ -148,7 +148,7 @@ TEST(SwapQueueTest, UnsuccessfulItemVerifyFunctor) {
EXPECT_DEATH(result = queue.Insert(&invalid_value), "");
}
-TEST(SwapQueueTest, UnSuccessfulItemVerifyInsert) {
+TEST(SwapQueueDeathTest, UnSuccessfulItemVerifyInsert) {
std::vector<int> template_element(kChunkSize);
SwapQueue<std::vector<int>,
SwapQueueItemVerifier<std::vector<int>, &LengthVerifierFunction>>
@@ -158,7 +158,7 @@ TEST(SwapQueueTest, UnSuccessfulItemVerifyInsert) {
EXPECT_DEATH(result = queue.Insert(&invalid_chunk), "");
}
-TEST(SwapQueueTest, UnSuccessfulItemVerifyRemove) {
+TEST(SwapQueueDeathTest, UnSuccessfulItemVerifyRemove) {
std::vector<int> template_element(kChunkSize);
SwapQueue<std::vector<int>,
SwapQueueItemVerifier<std::vector<int>, &LengthVerifierFunction>>
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/BUILD.gn b/chromium/third_party/webrtc/rtc_base/synchronization/BUILD.gn
index 3e7b22d4f93..f6e6d0bfaaf 100644
--- a/chromium/third_party/webrtc/rtc_base/synchronization/BUILD.gn
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/BUILD.gn
@@ -12,6 +12,38 @@ if (is_android) {
import("//build/config/android/rules.gni")
}
+rtc_library("yield") {
+ sources = [
+ "yield.cc",
+ "yield.h",
+ ]
+ deps = []
+}
+
+rtc_library("mutex") {
+ sources = [
+ "mutex.cc",
+ "mutex.h",
+ "mutex_critical_section.h",
+ "mutex_pthread.h",
+ ]
+ if (rtc_use_absl_mutex) {
+ sources += [ "mutex_abseil.h" ]
+ }
+
+ deps = [
+ ":yield",
+ "..:checks",
+ "..:macromagic",
+ "..:platform_thread_types",
+ "../system:unused",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ]
+ if (rtc_use_absl_mutex) {
+ absl_deps += [ "//third_party/abseil-cpp/absl/synchronization" ]
+ }
+}
+
rtc_library("rw_lock_wrapper") {
public = [ "rw_lock_wrapper.h" ]
sources = [ "rw_lock_wrapper.cc" ]
@@ -40,6 +72,7 @@ rtc_library("sequence_checker") {
"..:criticalsection",
"..:macromagic",
"..:platform_thread_types",
+ "..:stringutils",
"../../api/task_queue",
"../system:rtc_export",
]
@@ -50,8 +83,8 @@ rtc_library("yield_policy") {
"yield_policy.cc",
"yield_policy.h",
]
- deps = [
- "..:checks",
+ deps = [ "..:checks" ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/base:config",
"//third_party/abseil-cpp/absl/base:core_headers",
]
@@ -60,11 +93,30 @@ rtc_library("yield_policy") {
if (rtc_include_tests) {
rtc_library("synchronization_unittests") {
testonly = true
- sources = [ "yield_policy_unittest.cc" ]
+ sources = [
+ "mutex_unittest.cc",
+ "yield_policy_unittest.cc",
+ ]
deps = [
+ ":mutex",
+ ":yield",
":yield_policy",
+ "..:checks",
+ "..:macromagic",
+ "..:rtc_base",
"..:rtc_event",
"../../test:test_support",
+ "//third_party/google_benchmark",
+ ]
+ }
+
+ rtc_library("mutex_benchmark") {
+ testonly = true
+ sources = [ "mutex_benchmark.cc" ]
+ deps = [
+ ":mutex",
+ "../system:unused",
+ "//third_party/google_benchmark",
]
}
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/DEPS b/chromium/third_party/webrtc/rtc_base/synchronization/DEPS
new file mode 100644
index 00000000000..4ed1f2444bc
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/DEPS
@@ -0,0 +1,11 @@
+specific_include_rules = {
+ "mutex_abseil\.h": [
+ "+absl/synchronization"
+ ],
+ ".*_benchmark\.cc": [
+ "+benchmark",
+ ],
+ ".*_unittest\.cc": [
+ "+benchmark",
+ ]
+}
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex.cc b/chromium/third_party/webrtc/rtc_base/synchronization/mutex.cc
new file mode 100644
index 00000000000..6c2d6ff7f06
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex.cc
@@ -0,0 +1,39 @@
+/*
+ * 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
+ * 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/synchronization/mutex.h"
+
+#include "rtc_base/checks.h"
+#include "rtc_base/synchronization/yield.h"
+
+namespace webrtc {
+
+#if !defined(WEBRTC_ABSL_MUTEX)
+void GlobalMutex::Lock() {
+ while (mutex_locked_.exchange(1)) {
+ YieldCurrentThread();
+ }
+}
+
+void GlobalMutex::Unlock() {
+ int old = mutex_locked_.exchange(0);
+ RTC_DCHECK_EQ(old, 1) << "Unlock called without calling Lock first";
+}
+
+GlobalMutexLock::GlobalMutexLock(GlobalMutex* mutex) : mutex_(mutex) {
+ mutex_->Lock();
+}
+
+GlobalMutexLock::~GlobalMutexLock() {
+ mutex_->Unlock();
+}
+#endif // #if !defined(WEBRTC_ABSL_MUTEX)
+
+} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex.h b/chromium/third_party/webrtc/rtc_base/synchronization/mutex.h
new file mode 100644
index 00000000000..cc12c7edf0f
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex.h
@@ -0,0 +1,145 @@
+/*
+ * 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
+ * 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_SYNCHRONIZATION_MUTEX_H_
+#define RTC_BASE_SYNCHRONIZATION_MUTEX_H_
+
+#include <atomic>
+
+#include "absl/base/const_init.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/platform_thread_types.h"
+#include "rtc_base/system/unused.h"
+#include "rtc_base/thread_annotations.h"
+
+#if defined(WEBRTC_ABSL_MUTEX)
+#include "rtc_base/synchronization/mutex_abseil.h" // nogncheck
+#elif defined(WEBRTC_WIN)
+#include "rtc_base/synchronization/mutex_critical_section.h"
+#elif defined(WEBRTC_POSIX)
+#include "rtc_base/synchronization/mutex_pthread.h"
+#else
+#error Unsupported platform.
+#endif
+
+namespace webrtc {
+
+// The Mutex guarantees exclusive access and aims to follow Abseil semantics
+// (i.e. non-reentrant etc).
+class RTC_LOCKABLE Mutex final {
+ public:
+ Mutex() = default;
+ Mutex(const Mutex&) = delete;
+ Mutex& operator=(const Mutex&) = delete;
+
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() {
+ rtc::PlatformThreadRef current = CurrentThreadRefAssertingNotBeingHolder();
+ impl_.Lock();
+ // |holder_| changes from 0 to CurrentThreadRef().
+ holder_.store(current, std::memory_order_relaxed);
+ }
+ RTC_WARN_UNUSED_RESULT bool TryLock() RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+ rtc::PlatformThreadRef current = CurrentThreadRefAssertingNotBeingHolder();
+ if (impl_.TryLock()) {
+ // |holder_| changes from 0 to CurrentThreadRef().
+ holder_.store(current, std::memory_order_relaxed);
+ return true;
+ }
+ return false;
+ }
+ void Unlock() RTC_UNLOCK_FUNCTION() {
+ // |holder_| changes from CurrentThreadRef() to 0. If something else than
+ // CurrentThreadRef() is stored in |holder_|, the Unlock results in
+ // undefined behavior as mutexes can't be unlocked from another thread than
+ // the one that locked it, or called while not being locked.
+ holder_.store(0, std::memory_order_relaxed);
+ impl_.Unlock();
+ }
+
+ private:
+ rtc::PlatformThreadRef CurrentThreadRefAssertingNotBeingHolder() {
+ rtc::PlatformThreadRef holder = holder_.load(std::memory_order_relaxed);
+ rtc::PlatformThreadRef current = rtc::CurrentThreadRef();
+ // TODO(bugs.webrtc.org/11567): remove this temporary check after migrating
+ // fully to Mutex.
+ RTC_CHECK_NE(holder, current);
+ return current;
+ }
+
+ MutexImpl impl_;
+ // TODO(bugs.webrtc.org/11567): remove |holder_| after migrating fully to
+ // Mutex.
+ // |holder_| contains the PlatformThreadRef of the thread currently holding
+ // the lock, or 0.
+ // Remarks on the used memory orders: the atomic load in
+ // CurrentThreadRefAssertingNotBeingHolder() observes either of two things:
+ // 1. our own previous write to holder_ with our thread ID.
+ // 2. another thread (with ID y) writing y and then 0 from an initial value of
+ // 0. If we're observing case 1, our own stores are obviously ordered before
+ // the load, and hit the CHECK. If we're observing case 2, the value observed
+ // w.r.t |impl_| being locked depends on the memory order. Since we only care
+ // that it's different from CurrentThreadRef()), we use the more performant
+ // option, memory_order_relaxed.
+ std::atomic<rtc::PlatformThreadRef> holder_ = {0};
+};
+
+// MutexLock, for serializing execution through a scope.
+class RTC_SCOPED_LOCKABLE MutexLock final {
+ public:
+ MutexLock(const MutexLock&) = delete;
+ MutexLock& operator=(const MutexLock&) = delete;
+
+ explicit MutexLock(Mutex* mutex) RTC_EXCLUSIVE_LOCK_FUNCTION(mutex)
+ : mutex_(mutex) {
+ mutex->Lock();
+ }
+ ~MutexLock() RTC_UNLOCK_FUNCTION() { mutex_->Unlock(); }
+
+ private:
+ Mutex* mutex_;
+};
+
+// A mutex used to protect global variables. Do NOT use for other purposes.
+#if defined(WEBRTC_ABSL_MUTEX)
+using GlobalMutex = absl::Mutex;
+using GlobalMutexLock = absl::MutexLock;
+#else
+class RTC_LOCKABLE GlobalMutex final {
+ public:
+ GlobalMutex(const GlobalMutex&) = delete;
+ GlobalMutex& operator=(const GlobalMutex&) = delete;
+
+ constexpr explicit GlobalMutex(absl::ConstInitType /*unused*/)
+ : mutex_locked_(0) {}
+
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION();
+ void Unlock() RTC_UNLOCK_FUNCTION();
+
+ private:
+ std::atomic<int> mutex_locked_; // 0 means lock not taken, 1 means taken.
+};
+
+// GlobalMutexLock, for serializing execution through a scope.
+class RTC_SCOPED_LOCKABLE GlobalMutexLock final {
+ public:
+ GlobalMutexLock(const GlobalMutexLock&) = delete;
+ GlobalMutexLock& operator=(const GlobalMutexLock&) = delete;
+
+ explicit GlobalMutexLock(GlobalMutex* mutex) RTC_EXCLUSIVE_LOCK_FUNCTION();
+ ~GlobalMutexLock() RTC_UNLOCK_FUNCTION();
+
+ private:
+ GlobalMutex* mutex_;
+};
+#endif // if defined(WEBRTC_ABSL_MUTEX)
+
+} // namespace webrtc
+
+#endif // RTC_BASE_SYNCHRONIZATION_MUTEX_H_
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex_abseil.h b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_abseil.h
new file mode 100644
index 00000000000..4ad1d07eef1
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_abseil.h
@@ -0,0 +1,37 @@
+/*
+ * 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
+ * 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_SYNCHRONIZATION_MUTEX_ABSEIL_H_
+#define RTC_BASE_SYNCHRONIZATION_MUTEX_ABSEIL_H_
+
+#include "absl/synchronization/mutex.h"
+#include "rtc_base/thread_annotations.h"
+
+namespace webrtc {
+
+class RTC_LOCKABLE MutexImpl final {
+ public:
+ MutexImpl() = default;
+ MutexImpl(const MutexImpl&) = delete;
+ MutexImpl& operator=(const MutexImpl&) = delete;
+
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() { mutex_.Lock(); }
+ RTC_WARN_UNUSED_RESULT bool TryLock() RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+ return mutex_.TryLock();
+ }
+ void Unlock() RTC_UNLOCK_FUNCTION() { mutex_.Unlock(); }
+
+ private:
+ absl::Mutex mutex_;
+};
+
+} // namespace webrtc
+
+#endif // RTC_BASE_SYNCHRONIZATION_MUTEX_ABSEIL_H_
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex_benchmark.cc b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_benchmark.cc
new file mode 100644
index 00000000000..40adca65d86
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_benchmark.cc
@@ -0,0 +1,95 @@
+/*
+ * 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
+ * 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 "benchmark/benchmark.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "rtc_base/system/unused.h"
+
+namespace webrtc {
+
+class PerfTestData {
+ public:
+ PerfTestData() : cache_line_barrier_1_(), cache_line_barrier_2_() {
+ cache_line_barrier_1_[0]++; // Avoid 'is not used'.
+ cache_line_barrier_2_[0]++; // Avoid 'is not used'.
+ }
+
+ int AddToCounter(int add) {
+ MutexLock mu(&mu_);
+ my_counter_ += add;
+ return 0;
+ }
+
+ private:
+ uint8_t cache_line_barrier_1_[64];
+ Mutex mu_;
+ uint8_t cache_line_barrier_2_[64];
+ int64_t my_counter_ = 0;
+};
+
+void BM_LockWithMutex(benchmark::State& state) {
+ static PerfTestData test_data;
+ for (auto s : state) {
+ RTC_UNUSED(s);
+ benchmark::DoNotOptimize(test_data.AddToCounter(2));
+ }
+}
+
+BENCHMARK(BM_LockWithMutex)->Threads(1);
+BENCHMARK(BM_LockWithMutex)->Threads(2);
+BENCHMARK(BM_LockWithMutex)->Threads(4);
+BENCHMARK(BM_LockWithMutex)->ThreadPerCpu();
+
+} // namespace webrtc
+
+/*
+
+Results:
+
+NB when reproducing: Remember to turn of power management features such as CPU
+scaling before running!
+
+pthreads (Linux):
+----------------------------------------------------------------------
+Run on (12 X 4500 MHz CPU s)
+CPU Caches:
+ L1 Data 32 KiB (x6)
+ L1 Instruction 32 KiB (x6)
+ L2 Unified 1024 KiB (x6)
+ L3 Unified 8448 KiB (x1)
+Load Average: 0.26, 0.28, 0.44
+----------------------------------------------------------------------
+Benchmark Time CPU Iterations
+----------------------------------------------------------------------
+BM_LockWithMutex/threads:1 13.4 ns 13.4 ns 52192906
+BM_LockWithMutex/threads:2 44.2 ns 88.4 ns 8189944
+BM_LockWithMutex/threads:4 52.0 ns 198 ns 3743244
+BM_LockWithMutex/threads:12 84.9 ns 944 ns 733524
+
+std::mutex performs like the pthread implementation (Linux).
+
+Abseil (Linux):
+----------------------------------------------------------------------
+Run on (12 X 4500 MHz CPU s)
+CPU Caches:
+ L1 Data 32 KiB (x6)
+ L1 Instruction 32 KiB (x6)
+ L2 Unified 1024 KiB (x6)
+ L3 Unified 8448 KiB (x1)
+Load Average: 0.27, 0.24, 0.37
+----------------------------------------------------------------------
+Benchmark Time CPU Iterations
+----------------------------------------------------------------------
+BM_LockWithMutex/threads:1 15.0 ns 15.0 ns 46550231
+BM_LockWithMutex/threads:2 91.1 ns 182 ns 4059212
+BM_LockWithMutex/threads:4 40.8 ns 131 ns 5496560
+BM_LockWithMutex/threads:12 37.0 ns 130 ns 5377668
+
+*/
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex_critical_section.h b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_critical_section.h
new file mode 100644
index 00000000000..d206794988b
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_critical_section.h
@@ -0,0 +1,54 @@
+/*
+ * 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
+ * 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_SYNCHRONIZATION_MUTEX_CRITICAL_SECTION_H_
+#define RTC_BASE_SYNCHRONIZATION_MUTEX_CRITICAL_SECTION_H_
+
+#if defined(WEBRTC_WIN)
+// clang-format off
+// clang formating would change include order.
+
+// Include winsock2.h before including <windows.h> to maintain consistency with
+// win32.h. To include win32.h directly, it must be broken out into its own
+// build target.
+#include <winsock2.h>
+#include <windows.h>
+#include <sal.h> // must come after windows headers.
+// clang-format on
+
+#include "rtc_base/thread_annotations.h"
+
+namespace webrtc {
+
+class RTC_LOCKABLE MutexImpl final {
+ public:
+ MutexImpl() { InitializeCriticalSection(&critical_section_); }
+ MutexImpl(const MutexImpl&) = delete;
+ MutexImpl& operator=(const MutexImpl&) = delete;
+ ~MutexImpl() { DeleteCriticalSection(&critical_section_); }
+
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() {
+ EnterCriticalSection(&critical_section_);
+ }
+ RTC_WARN_UNUSED_RESULT bool TryLock() RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+ return TryEnterCriticalSection(&critical_section_) != FALSE;
+ }
+ void Unlock() RTC_UNLOCK_FUNCTION() {
+ LeaveCriticalSection(&critical_section_);
+ }
+
+ private:
+ CRITICAL_SECTION critical_section_;
+};
+
+} // namespace webrtc
+
+#endif // #if defined(WEBRTC_WIN)
+#endif // RTC_BASE_SYNCHRONIZATION_MUTEX_CRITICAL_SECTION_H_
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex_pthread.h b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_pthread.h
new file mode 100644
index 00000000000..c9496e72c9a
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_pthread.h
@@ -0,0 +1,53 @@
+/*
+ * 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
+ * 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_SYNCHRONIZATION_MUTEX_PTHREAD_H_
+#define RTC_BASE_SYNCHRONIZATION_MUTEX_PTHREAD_H_
+
+#if defined(WEBRTC_POSIX)
+
+#include <pthread.h>
+#if defined(WEBRTC_MAC)
+#include <pthread_spis.h>
+#endif
+
+#include "rtc_base/thread_annotations.h"
+
+namespace webrtc {
+
+class RTC_LOCKABLE MutexImpl final {
+ public:
+ MutexImpl() {
+ pthread_mutexattr_t mutex_attribute;
+ pthread_mutexattr_init(&mutex_attribute);
+#if defined(WEBRTC_MAC)
+ pthread_mutexattr_setpolicy_np(&mutex_attribute,
+ _PTHREAD_MUTEX_POLICY_FIRSTFIT);
+#endif
+ pthread_mutex_init(&mutex_, &mutex_attribute);
+ pthread_mutexattr_destroy(&mutex_attribute);
+ }
+ MutexImpl(const MutexImpl&) = delete;
+ MutexImpl& operator=(const MutexImpl&) = delete;
+ ~MutexImpl() { pthread_mutex_destroy(&mutex_); }
+
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() { pthread_mutex_lock(&mutex_); }
+ RTC_WARN_UNUSED_RESULT bool TryLock() RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+ return pthread_mutex_trylock(&mutex_) == 0;
+ }
+ void Unlock() RTC_UNLOCK_FUNCTION() { pthread_mutex_unlock(&mutex_); }
+
+ private:
+ pthread_mutex_t mutex_;
+};
+
+} // namespace webrtc
+#endif // #if defined(WEBRTC_POSIX)
+#endif // RTC_BASE_SYNCHRONIZATION_MUTEX_PTHREAD_H_
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/mutex_unittest.cc b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_unittest.cc
new file mode 100644
index 00000000000..b8c45d0a8cf
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/mutex_unittest.cc
@@ -0,0 +1,206 @@
+/*
+ * 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
+ * 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/synchronization/mutex.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <memory>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/event.h"
+#include "rtc_base/location.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/synchronization/yield.h"
+#include "rtc_base/thread.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::rtc::Event;
+using ::rtc::Message;
+using ::rtc::MessageHandler;
+using ::rtc::Thread;
+
+constexpr int kNumThreads = 16;
+
+template <class MutexType>
+class RTC_LOCKABLE RawMutexLocker {
+ public:
+ explicit RawMutexLocker(MutexType& mutex) : mutex_(mutex) {}
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() { mutex_.Lock(); }
+ void Unlock() RTC_UNLOCK_FUNCTION() { mutex_.Unlock(); }
+
+ private:
+ MutexType& mutex_;
+};
+
+class RTC_LOCKABLE RawMutexTryLocker {
+ public:
+ explicit RawMutexTryLocker(Mutex& mutex) : mutex_(mutex) {}
+ void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION() {
+ while (!mutex_.TryLock()) {
+ YieldCurrentThread();
+ }
+ }
+ void Unlock() RTC_UNLOCK_FUNCTION() { mutex_.Unlock(); }
+
+ private:
+ Mutex& mutex_;
+};
+
+template <class MutexType, class MutexLockType>
+class MutexLockLocker {
+ public:
+ explicit MutexLockLocker(MutexType& mutex) : mutex_(mutex) {}
+ void Lock() { lock_ = std::make_unique<MutexLockType>(&mutex_); }
+ void Unlock() { lock_ = nullptr; }
+
+ private:
+ MutexType& mutex_;
+ std::unique_ptr<MutexLockType> lock_;
+};
+
+template <class MutexType, class MutexLocker>
+class LockRunner : public rtc::MessageHandlerAutoCleanup {
+ public:
+ template <typename... Args>
+ explicit LockRunner(Args... args)
+ : threads_active_(0),
+ start_event_(true, false),
+ done_event_(true, false),
+ shared_value_(0),
+ mutex_(args...),
+ locker_(mutex_) {}
+
+ bool Run() {
+ // Signal all threads to start.
+ start_event_.Set();
+
+ // Wait for all threads to finish.
+ return done_event_.Wait(kLongTime);
+ }
+
+ void SetExpectedThreadCount(int count) { threads_active_ = count; }
+
+ int shared_value() {
+ int shared_value;
+ locker_.Lock();
+ shared_value = shared_value_;
+ locker_.Unlock();
+ return shared_value_;
+ }
+
+ void OnMessage(Message* msg) override {
+ ASSERT_TRUE(start_event_.Wait(kLongTime));
+ locker_.Lock();
+
+ EXPECT_EQ(0, shared_value_);
+ int old = shared_value_;
+
+ // Use a loop to increase the chance of race. If the |locker_|
+ // implementation is faulty, it would be improbable that the error slips
+ // through.
+ for (int i = 0; i < kOperationsToRun; ++i) {
+ benchmark::DoNotOptimize(++shared_value_);
+ }
+ EXPECT_EQ(old + kOperationsToRun, shared_value_);
+ shared_value_ = 0;
+
+ locker_.Unlock();
+ if (threads_active_.fetch_sub(1) == 1) {
+ done_event_.Set();
+ }
+ }
+
+ private:
+ static constexpr int kLongTime = 10000; // 10 seconds
+ static constexpr int kOperationsToRun = 1000;
+
+ std::atomic<int> threads_active_;
+ Event start_event_;
+ Event done_event_;
+ int shared_value_;
+ MutexType mutex_;
+ MutexLocker locker_;
+};
+
+void StartThreads(std::vector<std::unique_ptr<Thread>>& threads,
+ MessageHandler* handler) {
+ for (int i = 0; i < kNumThreads; ++i) {
+ std::unique_ptr<Thread> thread(Thread::Create());
+ thread->Start();
+ thread->Post(RTC_FROM_HERE, handler);
+ threads.push_back(std::move(thread));
+ }
+}
+
+TEST(MutexTest, ProtectsSharedResourceWithMutexAndRawMutexLocker) {
+ std::vector<std::unique_ptr<Thread>> threads;
+ LockRunner<Mutex, RawMutexLocker<Mutex>> runner;
+ StartThreads(threads, &runner);
+ runner.SetExpectedThreadCount(kNumThreads);
+ EXPECT_TRUE(runner.Run());
+ EXPECT_EQ(0, runner.shared_value());
+}
+
+TEST(MutexTest, ProtectsSharedResourceWithMutexAndRawMutexTryLocker) {
+ std::vector<std::unique_ptr<Thread>> threads;
+ LockRunner<Mutex, RawMutexTryLocker> runner;
+ StartThreads(threads, &runner);
+ runner.SetExpectedThreadCount(kNumThreads);
+ EXPECT_TRUE(runner.Run());
+ EXPECT_EQ(0, runner.shared_value());
+}
+
+TEST(MutexTest, ProtectsSharedResourceWithMutexAndMutexLocker) {
+ std::vector<std::unique_ptr<Thread>> threads;
+ LockRunner<Mutex, MutexLockLocker<Mutex, MutexLock>> runner;
+ StartThreads(threads, &runner);
+ runner.SetExpectedThreadCount(kNumThreads);
+ EXPECT_TRUE(runner.Run());
+ EXPECT_EQ(0, runner.shared_value());
+}
+
+TEST(MutexTest, ProtectsSharedResourceWithGlobalMutexAndRawMutexLocker) {
+ std::vector<std::unique_ptr<Thread>> threads;
+ LockRunner<GlobalMutex, RawMutexLocker<GlobalMutex>> runner(absl::kConstInit);
+ StartThreads(threads, &runner);
+ runner.SetExpectedThreadCount(kNumThreads);
+ EXPECT_TRUE(runner.Run());
+ EXPECT_EQ(0, runner.shared_value());
+}
+
+TEST(MutexTest, ProtectsSharedResourceWithGlobalMutexAndMutexLocker) {
+ std::vector<std::unique_ptr<Thread>> threads;
+ LockRunner<GlobalMutex, MutexLockLocker<GlobalMutex, GlobalMutexLock>> runner(
+ absl::kConstInit);
+ StartThreads(threads, &runner);
+ runner.SetExpectedThreadCount(kNumThreads);
+ EXPECT_TRUE(runner.Run());
+ EXPECT_EQ(0, runner.shared_value());
+}
+
+TEST(MutexTest, GlobalMutexCanHaveStaticStorageDuration) {
+ ABSL_CONST_INIT static GlobalMutex global_lock(absl::kConstInit);
+ global_lock.Lock();
+ global_lock.Unlock();
+}
+
+} // namespace
+} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.cc b/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.cc
index d64f32a616d..ff433db137f 100644
--- a/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.cc
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.cc
@@ -13,6 +13,8 @@
#include <dispatch/dispatch.h>
#endif
+#include "rtc_base/strings/string_builder.h"
+
namespace webrtc {
namespace {
// On Mac, returns the label of the current dispatch queue; elsewhere, return
@@ -24,8 +26,16 @@ const void* GetSystemQueueRef() {
return nullptr;
#endif
}
+
} // namespace
+std::string ExpectationToString(const webrtc::SequenceChecker* checker) {
+#if RTC_DCHECK_IS_ON
+ return checker->ExpectationToString();
+#endif
+ return std::string();
+}
+
SequenceCheckerImpl::SequenceCheckerImpl()
: attached_(true),
valid_thread_(rtc::CurrentThreadRef()),
@@ -62,4 +72,41 @@ void SequenceCheckerImpl::Detach() {
// reset on the next call to IsCurrent().
}
+#if RTC_DCHECK_IS_ON
+std::string SequenceCheckerImpl::ExpectationToString() const {
+ const TaskQueueBase* const current_queue = TaskQueueBase::Current();
+ const rtc::PlatformThreadRef current_thread = rtc::CurrentThreadRef();
+ const void* const current_system_queue = GetSystemQueueRef();
+ rtc::CritScope scoped_lock(&lock_);
+ if (!attached_)
+ return "Checker currently not attached.";
+
+ // The format of the string is meant to compliment the one we have inside of
+ // FatalLog() (checks.cc). Example:
+ //
+ // # Expected: TQ: 0x0 SysQ: 0x7fff69541330 Thread: 0x11dcf6dc0
+ // # Actual: TQ: 0x7fa8f0604190 SysQ: 0x7fa8f0604a30 Thread: 0x700006f1a000
+ // TaskQueue doesn't match
+
+ rtc::StringBuilder message;
+ message.AppendFormat(
+ "# Expected: TQ: %p SysQ: %p Thread: %p\n"
+ "# Actual: TQ: %p SysQ: %p Thread: %p\n",
+ valid_queue_, valid_system_queue_,
+ reinterpret_cast<const void*>(valid_thread_), current_queue,
+ current_system_queue, reinterpret_cast<const void*>(current_thread));
+
+ if ((valid_queue_ || current_queue) && valid_queue_ != current_queue) {
+ message << "TaskQueue doesn't match\n";
+ } else if (valid_system_queue_ &&
+ valid_system_queue_ != current_system_queue) {
+ message << "System queue doesn't match\n";
+ } else if (!rtc::IsThreadRefEqual(valid_thread_, current_thread)) {
+ message << "Threads don't match\n";
+ }
+
+ return message.Release();
+}
+#endif // RTC_DCHECK_IS_ON
+
} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.h b/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.h
index fe644fa14e3..fd0a69983af 100644
--- a/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.h
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker.h
@@ -10,6 +10,8 @@
#ifndef RTC_BASE_SYNCHRONIZATION_SEQUENCE_CHECKER_H_
#define RTC_BASE_SYNCHRONIZATION_SEQUENCE_CHECKER_H_
+#include <type_traits>
+
#include "api/task_queue/task_queue_base.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/platform_thread_types.h"
@@ -34,6 +36,11 @@ class RTC_EXPORT SequenceCheckerImpl {
// used exclusively on another thread.
void Detach();
+ // Returns a string that is formatted to match with the error string printed
+ // by RTC_CHECK() when a condition is not met.
+ // This is used in conjunction with the RTC_DCHECK_RUN_ON() macro.
+ std::string ExpectationToString() const;
+
private:
rtc::CriticalSection lock_;
// These are mutable so that IsCurrent can set them.
@@ -162,8 +169,19 @@ class RTC_SCOPED_LOCKABLE SequenceCheckerScope {
#define RTC_RUN_ON(x) \
RTC_THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x))
+namespace webrtc {
+std::string ExpectationToString(const webrtc::SequenceChecker* checker);
+
+// Catch-all implementation for types other than explicitly supported above.
+template <typename ThreadLikeObject>
+std::string ExpectationToString(const ThreadLikeObject*) {
+ return std::string();
+}
+
+} // namespace webrtc
+
#define RTC_DCHECK_RUN_ON(x) \
webrtc::webrtc_seq_check_impl::SequenceCheckerScope seq_check_scope(x); \
- RTC_DCHECK((x)->IsCurrent())
+ RTC_DCHECK((x)->IsCurrent()) << webrtc::ExpectationToString(x)
#endif // RTC_BASE_SYNCHRONIZATION_SEQUENCE_CHECKER_H_
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker_unittest.cc b/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker_unittest.cc
index 1e62e9759b4..6fcb522c545 100644
--- a/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/sequence_checker_unittest.cc
@@ -31,7 +31,7 @@ class CompileTimeTestForGuardedBy {
int CalledOnSequence() RTC_RUN_ON(sequence_checker_) { return guarded_; }
void CallMeFromSequence() {
- RTC_DCHECK_RUN_ON(&sequence_checker_) << "Should be called on sequence";
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
guarded_ = 41;
}
@@ -158,7 +158,12 @@ void TestAnnotationsOnWrongQueue() {
}
#if RTC_DCHECK_IS_ON
-TEST(SequenceCheckerTest, TestAnnotationsOnWrongQueueDebug) {
+// Note: Ending the test suite name with 'DeathTest' is important as it causes
+// gtest to order this test before any other non-death-tests, to avoid potential
+// global process state pollution such as shared worker threads being started
+// (e.g. a side effect of calling InitCocoaMultiThreading() on Mac causes one or
+// two additional threads to be created).
+TEST(SequenceCheckerDeathTest, TestAnnotationsOnWrongQueueDebug) {
ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, "");
}
#else
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/yield.cc b/chromium/third_party/webrtc/rtc_base/synchronization/yield.cc
new file mode 100644
index 00000000000..cbb58d12ab0
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/yield.cc
@@ -0,0 +1,36 @@
+/*
+ * 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
+ * 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/synchronization/yield.h"
+
+#if defined(WEBRTC_WIN)
+#include <windows.h>
+#else
+#include <sched.h>
+#include <time.h>
+#endif
+
+namespace webrtc {
+
+void YieldCurrentThread() {
+ // TODO(bugs.webrtc.org/11634): use dedicated OS functionality instead of
+ // sleep for yielding.
+#if defined(WEBRTC_WIN)
+ ::Sleep(0);
+#elif defined(WEBRTC_MAC) && defined(RTC_USE_NATIVE_MUTEX_ON_MAC) && \
+ !RTC_USE_NATIVE_MUTEX_ON_MAC
+ sched_yield();
+#else
+ static const struct timespec ts_null = {0};
+ nanosleep(&ts_null, nullptr);
+#endif
+}
+
+} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/yield.h b/chromium/third_party/webrtc/rtc_base/synchronization/yield.h
new file mode 100644
index 00000000000..d4f5f99f375
--- /dev/null
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/yield.h
@@ -0,0 +1,20 @@
+/*
+ * 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
+ * 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_SYNCHRONIZATION_YIELD_H_
+#define RTC_BASE_SYNCHRONIZATION_YIELD_H_
+
+namespace webrtc {
+
+// Request rescheduling of threads.
+void YieldCurrentThread();
+
+} // namespace webrtc
+
+#endif // RTC_BASE_SYNCHRONIZATION_YIELD_H_
diff --git a/chromium/third_party/webrtc/rtc_base/synchronization/yield_policy_unittest.cc b/chromium/third_party/webrtc/rtc_base/synchronization/yield_policy_unittest.cc
index e0c622510a1..0bf38f4537c 100644
--- a/chromium/third_party/webrtc/rtc_base/synchronization/yield_policy_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/synchronization/yield_policy_unittest.cc
@@ -20,7 +20,7 @@ namespace rtc {
namespace {
class MockYieldHandler : public YieldInterface {
public:
- MOCK_METHOD0(YieldExecution, void());
+ MOCK_METHOD(void, YieldExecution, (), (override));
};
} // namespace
TEST(YieldPolicyTest, HandlerReceivesYieldSignalWhenSet) {
diff --git a/chromium/third_party/webrtc/rtc_base/system/BUILD.gn b/chromium/third_party/webrtc/rtc_base/system/BUILD.gn
index 79cb301038f..98867588ccc 100644
--- a/chromium/third_party/webrtc/rtc_base/system/BUILD.gn
+++ b/chromium/third_party/webrtc/rtc_base/system/BUILD.gn
@@ -75,10 +75,8 @@ rtc_source_set("thread_registry") {
deps = [ "..:rtc_base_approved" ]
if (is_android && !build_with_chromium) {
sources += [ "thread_registry.cc" ]
- deps += [
- "../../sdk/android:native_api_stacktrace",
- "//third_party/abseil-cpp/absl/base:core_headers",
- ]
+ deps += [ "../../sdk/android:native_api_stacktrace" ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ]
}
}
diff --git a/chromium/third_party/webrtc/rtc_base/task_utils/BUILD.gn b/chromium/third_party/webrtc/rtc_base/task_utils/BUILD.gn
index 1882cd9ee8d..54f9a048f02 100644
--- a/chromium/third_party/webrtc/rtc_base/task_utils/BUILD.gn
+++ b/chromium/third_party/webrtc/rtc_base/task_utils/BUILD.gn
@@ -21,9 +21,10 @@ rtc_library("repeating_task") {
"../../api/task_queue",
"../../api/units:time_delta",
"../../api/units:timestamp",
+ "../../system_wrappers:system_wrappers",
"../synchronization:sequence_checker",
- "//third_party/abseil-cpp/absl/memory",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
}
rtc_library("pending_task_safety_flag") {
@@ -81,7 +82,7 @@ if (rtc_include_tests) {
":to_queued_task",
"../../api/task_queue",
"../../test:test_support",
- "//third_party/abseil-cpp/absl/memory",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
}
}
diff --git a/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.cc b/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.cc
index 71911e6982c..574e6331f14 100644
--- a/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.cc
+++ b/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.cc
@@ -17,17 +17,18 @@
namespace webrtc {
namespace webrtc_repeating_task_impl {
+
RepeatingTaskBase::RepeatingTaskBase(TaskQueueBase* task_queue,
- TimeDelta first_delay)
+ TimeDelta first_delay,
+ Clock* clock)
: task_queue_(task_queue),
- next_run_time_(Timestamp::Micros(rtc::TimeMicros()) + first_delay) {
- sequence_checker_.Detach();
-}
+ clock_(clock),
+ next_run_time_(clock_->CurrentTime() + first_delay) {}
RepeatingTaskBase::~RepeatingTaskBase() = default;
bool RepeatingTaskBase::Run() {
- RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK_RUN_ON(task_queue_);
// Return true to tell the TaskQueue to destruct this object.
if (next_run_time_.IsPlusInfinity())
return true;
@@ -40,7 +41,7 @@ bool RepeatingTaskBase::Run() {
return true;
RTC_DCHECK(delay.IsFinite());
- TimeDelta lost_time = Timestamp::Micros(rtc::TimeMicros()) - next_run_time_;
+ TimeDelta lost_time = clock_->CurrentTime() - next_run_time_;
next_run_time_ += delay;
delay -= lost_time;
delay = std::max(delay, TimeDelta::Zero());
@@ -53,7 +54,7 @@ bool RepeatingTaskBase::Run() {
}
void RepeatingTaskBase::Stop() {
- RTC_DCHECK_RUN_ON(&sequence_checker_);
+ RTC_DCHECK_RUN_ON(task_queue_);
RTC_DCHECK(next_run_time_.IsFinite());
next_run_time_ = Timestamp::PlusInfinity();
}
diff --git a/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.h b/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.h
index 75d03bfe5e6..487b7d19d46 100644
--- a/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.h
+++ b/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task.h
@@ -19,7 +19,7 @@
#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
-#include "rtc_base/synchronization/sequence_checker.h"
+#include "system_wrappers/include/clock.h"
namespace webrtc {
@@ -28,7 +28,9 @@ class RepeatingTaskHandle;
namespace webrtc_repeating_task_impl {
class RepeatingTaskBase : public QueuedTask {
public:
- RepeatingTaskBase(TaskQueueBase* task_queue, TimeDelta first_delay);
+ RepeatingTaskBase(TaskQueueBase* task_queue,
+ TimeDelta first_delay,
+ Clock* clock);
~RepeatingTaskBase() override;
void Stop();
@@ -39,16 +41,10 @@ class RepeatingTaskBase : public QueuedTask {
bool Run() final;
TaskQueueBase* const task_queue_;
+ Clock* const clock_;
// This is always finite, except for the special case where it's PlusInfinity
// to signal that the task should stop.
- Timestamp next_run_time_ RTC_GUARDED_BY(sequence_checker_);
- // We use a SequenceChecker to check for correct usage instead of using
- // RTC_DCHECK_RUN_ON(task_queue_). This is to work around a compatibility
- // issue with some TQ implementations such as rtc::Thread that don't
- // consistently set themselves as the 'current' TQ when running tasks.
- // The SequenceChecker detects those implementations differently but gives
- // the same effect as far as thread safety goes.
- SequenceChecker sequence_checker_;
+ Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
};
// The template closure pattern is based on rtc::ClosureTask.
@@ -57,8 +53,9 @@ class RepeatingTaskImpl final : public RepeatingTaskBase {
public:
RepeatingTaskImpl(TaskQueueBase* task_queue,
TimeDelta first_delay,
- Closure&& closure)
- : RepeatingTaskBase(task_queue, first_delay),
+ Closure&& closure,
+ Clock* clock)
+ : RepeatingTaskBase(task_queue, first_delay, clock),
closure_(std::forward<Closure>(closure)) {
static_assert(
std::is_same<TimeDelta,
@@ -98,10 +95,11 @@ class RepeatingTaskHandle {
// repeated task is owned by the TaskQueue.
template <class Closure>
static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
- Closure&& closure) {
+ Closure&& closure,
+ Clock* clock = Clock::GetRealTimeClock()) {
auto repeating_task = std::make_unique<
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
- task_queue, TimeDelta::Zero(), std::forward<Closure>(closure));
+ task_queue, TimeDelta::Zero(), std::forward<Closure>(closure), clock);
auto* repeating_task_ptr = repeating_task.get();
task_queue->PostTask(std::move(repeating_task));
return RepeatingTaskHandle(repeating_task_ptr);
@@ -110,12 +108,14 @@ class RepeatingTaskHandle {
// DelayedStart is equivalent to Start except that the first invocation of the
// closure will be delayed by the given amount.
template <class Closure>
- static RepeatingTaskHandle DelayedStart(TaskQueueBase* task_queue,
- TimeDelta first_delay,
- Closure&& closure) {
+ static RepeatingTaskHandle DelayedStart(
+ TaskQueueBase* task_queue,
+ TimeDelta first_delay,
+ Closure&& closure,
+ Clock* clock = Clock::GetRealTimeClock()) {
auto repeating_task = std::make_unique<
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
- task_queue, first_delay, std::forward<Closure>(closure));
+ task_queue, first_delay, std::forward<Closure>(closure), clock);
auto* repeating_task_ptr = repeating_task.get();
task_queue->PostDelayedTask(std::move(repeating_task), first_delay.ms());
return RepeatingTaskHandle(repeating_task_ptr);
diff --git a/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task_unittest.cc b/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task_unittest.cc
index 83efb29209a..2fb15d1e5a3 100644
--- a/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/task_utils/repeating_task_unittest.cc
@@ -40,8 +40,23 @@ void Sleep(TimeDelta time_delta) {
class MockClosure {
public:
- MOCK_METHOD0(Call, TimeDelta());
- MOCK_METHOD0(Delete, void());
+ MOCK_METHOD(TimeDelta, Call, ());
+ MOCK_METHOD(void, Delete, ());
+};
+
+class MockTaskQueue : public TaskQueueBase {
+ public:
+ MockTaskQueue() : task_queue_setter_(this) {}
+
+ MOCK_METHOD(void, Delete, (), (override));
+ MOCK_METHOD(void, PostTask, (std::unique_ptr<QueuedTask> task), (override));
+ MOCK_METHOD(void,
+ PostDelayedTask,
+ (std::unique_ptr<QueuedTask> task, uint32_t milliseconds),
+ (override));
+
+ private:
+ CurrentTaskQueueSetter task_queue_setter_;
};
class MoveOnlyClosure {
@@ -228,4 +243,37 @@ TEST(RepeatingTaskTest, Example) {
// task queue destruction and running the desctructor closure.
}
+TEST(RepeatingTaskTest, ClockIntegration) {
+ std::unique_ptr<QueuedTask> delayed_task;
+ uint32_t expected_ms = 0;
+ SimulatedClock clock(Timestamp::Millis(0));
+
+ NiceMock<MockTaskQueue> task_queue;
+ ON_CALL(task_queue, PostDelayedTask)
+ .WillByDefault(
+ Invoke([&delayed_task, &expected_ms](std::unique_ptr<QueuedTask> task,
+ uint32_t milliseconds) {
+ EXPECT_EQ(milliseconds, expected_ms);
+ delayed_task = std::move(task);
+ }));
+
+ expected_ms = 100;
+ RepeatingTaskHandle handle = RepeatingTaskHandle::DelayedStart(
+ &task_queue, TimeDelta::Millis(100),
+ [&clock]() {
+ EXPECT_EQ(Timestamp::Millis(100), clock.CurrentTime());
+ // Simulate work happening for 10ms.
+ clock.AdvanceTimeMilliseconds(10);
+ return TimeDelta::Millis(100);
+ },
+ &clock);
+
+ clock.AdvanceTimeMilliseconds(100);
+ QueuedTask* task_to_run = delayed_task.release();
+ expected_ms = 90;
+ EXPECT_FALSE(task_to_run->Run());
+ EXPECT_NE(nullptr, delayed_task.get());
+ handle.Stop();
+}
+
} // namespace webrtc
diff --git a/chromium/third_party/webrtc/rtc_base/thread.cc b/chromium/third_party/webrtc/rtc_base/thread.cc
index 0fb2e813e03..566edff13fd 100644
--- a/chromium/third_party/webrtc/rtc_base/thread.cc
+++ b/chromium/third_party/webrtc/rtc_base/thread.cc
@@ -32,8 +32,10 @@
#include "rtc_base/atomic_ops.h"
#include "rtc_base/checks.h"
#include "rtc_base/critical_section.h"
+#include "rtc_base/event.h"
#include "rtc_base/logging.h"
#include "rtc_base/null_socket_server.h"
+#include "rtc_base/synchronization/sequence_checker.h"
#include "rtc_base/task_utils/to_queued_task.h"
#include "rtc_base/time_utils.h"
#include "rtc_base/trace_event.h"
@@ -72,7 +74,7 @@ const int kSlowDispatchLoggingThreshold = 50; // 50 ms
class MessageHandlerWithTask final : public MessageHandler {
public:
- MessageHandlerWithTask() = default;
+ MessageHandlerWithTask() : MessageHandler(false) {}
void OnMessage(Message* msg) override {
static_cast<rtc_thread_internal::MessageLikeTask*>(msg->pdata)->Run();
@@ -163,13 +165,16 @@ void ThreadManager::RemoveFromSendGraph(Thread* thread) {
void ThreadManager::RegisterSendAndCheckForCycles(Thread* source,
Thread* target) {
+ RTC_DCHECK(source);
+ RTC_DCHECK(target);
+
CritScope cs(&crit_);
std::deque<Thread*> all_targets({target});
// We check the pre-existing who-sends-to-who graph for any path from target
// to source. This loop is guaranteed to terminate because per the send graph
// invariant, there are no cycles in the graph.
- for (auto it = all_targets.begin(); it != all_targets.end(); ++it) {
- const auto& targets = send_graph_[*it];
+ for (size_t i = 0; i < all_targets.size(); i++) {
+ const auto& targets = send_graph_[all_targets[i]];
all_targets.insert(all_targets.end(), targets.begin(), targets.end());
}
RTC_CHECK_EQ(absl::c_count(all_targets, source), 0)
@@ -296,6 +301,21 @@ void ThreadManager::SetCurrentThread(Thread* thread) {
RTC_DLOG(LS_ERROR) << "SetCurrentThread: Overwriting an existing value?";
}
#endif // RTC_DLOG_IS_ON
+
+ if (thread) {
+ thread->EnsureIsCurrentTaskQueue();
+ } else {
+ Thread* current = CurrentThread();
+ if (current) {
+ // The current thread is being cleared, e.g. as a result of
+ // UnwrapCurrent() being called or when a thread is being stopped
+ // (see PreRun()). This signals that the Thread instance is being detached
+ // from the thread, which also means that TaskQueue::Current() must not
+ // return a pointer to the Thread instance.
+ current->ClearCurrentTaskQueue();
+ }
+ }
+
SetCurrentThreadInternal(thread);
}
@@ -824,7 +844,6 @@ void* Thread::PreRun(void* pv) {
Thread* thread = static_cast<Thread*>(pv);
ThreadManager::Instance()->SetCurrentThread(thread);
rtc::SetCurrentThreadName(thread->name_.c_str());
- CurrentTaskQueueSetter set_current_task_queue(thread);
#if defined(WEBRTC_MAC)
ScopedAutoReleasePool pool;
#endif
@@ -875,45 +894,62 @@ void Thread::Send(const Location& posted_from,
AssertBlockingIsAllowedOnCurrentThread();
- AutoThread thread;
Thread* current_thread = Thread::Current();
- RTC_DCHECK(current_thread != nullptr); // AutoThread ensures this
+
#if RTC_DCHECK_IS_ON
- ThreadManager::Instance()->RegisterSendAndCheckForCycles(current_thread,
- this);
+ if (current_thread) {
+ RTC_DCHECK(current_thread->IsInvokeToThreadAllowed(this));
+ ThreadManager::Instance()->RegisterSendAndCheckForCycles(current_thread,
+ this);
+ }
#endif
+
+ // Perhaps down the line we can get rid of this workaround and always require
+ // current_thread to be valid when Send() is called.
+ std::unique_ptr<rtc::Event> done_event;
+ if (!current_thread)
+ done_event.reset(new rtc::Event());
+
bool ready = false;
- PostTask(
- webrtc::ToQueuedTask([msg]() mutable { msg.phandler->OnMessage(&msg); },
- [this, &ready, current_thread] {
- CritScope cs(&crit_);
- ready = true;
- current_thread->socketserver()->WakeUp();
- }));
-
- bool waited = false;
- crit_.Enter();
- while (!ready) {
- crit_.Leave();
- current_thread->socketserver()->Wait(kForever, false);
- waited = true;
+ PostTask(webrtc::ToQueuedTask(
+ [&msg]() mutable { msg.phandler->OnMessage(&msg); },
+ [this, &ready, current_thread, done = done_event.get()] {
+ if (current_thread) {
+ CritScope cs(&crit_);
+ ready = true;
+ current_thread->socketserver()->WakeUp();
+ } else {
+ done->Set();
+ }
+ }));
+
+ if (current_thread) {
+ bool waited = false;
crit_.Enter();
- }
- crit_.Leave();
-
- // Our Wait loop above may have consumed some WakeUp events for this
- // Thread, that weren't relevant to this Send. Losing these WakeUps can
- // cause problems for some SocketServers.
- //
- // Concrete example:
- // Win32SocketServer on thread A calls Send on thread B. While processing the
- // message, thread B Posts a message to A. We consume the wakeup for that
- // Post while waiting for the Send to complete, which means that when we exit
- // this loop, we need to issue another WakeUp, or else the Posted message
- // won't be processed in a timely manner.
-
- if (waited) {
- current_thread->socketserver()->WakeUp();
+ while (!ready) {
+ crit_.Leave();
+ current_thread->socketserver()->Wait(kForever, false);
+ waited = true;
+ crit_.Enter();
+ }
+ crit_.Leave();
+
+ // Our Wait loop above may have consumed some WakeUp events for this
+ // Thread, that weren't relevant to this Send. Losing these WakeUps can
+ // cause problems for some SocketServers.
+ //
+ // Concrete example:
+ // Win32SocketServer on thread A calls Send on thread B. While processing
+ // the message, thread B Posts a message to A. We consume the wakeup for
+ // that Post while waiting for the Send to complete, which means that when
+ // we exit this loop, we need to issue another WakeUp, or else the Posted
+ // message won't be processed in a timely manner.
+
+ if (waited) {
+ current_thread->socketserver()->WakeUp();
+ }
+ } else {
+ done_event->Wait(rtc::Event::kForever);
}
}
@@ -925,7 +961,7 @@ void Thread::InvokeInternal(const Location& posted_from,
class FunctorMessageHandler : public MessageHandler {
public:
explicit FunctorMessageHandler(rtc::FunctionView<void()> functor)
- : functor_(functor) {}
+ : MessageHandler(false), functor_(functor) {}
void OnMessage(Message* msg) override { functor_(); }
private:
@@ -935,6 +971,17 @@ void Thread::InvokeInternal(const Location& posted_from,
Send(posted_from, &handler);
}
+// Called by the ThreadManager when being set as the current thread.
+void Thread::EnsureIsCurrentTaskQueue() {
+ task_queue_registration_ =
+ std::make_unique<TaskQueueBase::CurrentTaskQueueSetter>(this);
+}
+
+// Called by the ThreadManager when being set as the current thread.
+void Thread::ClearCurrentTaskQueue() {
+ task_queue_registration_.reset();
+}
+
void Thread::QueuedTaskHandler::OnMessage(Message* msg) {
RTC_DCHECK(msg);
auto* data = static_cast<ScopedMessageData<webrtc::QueuedTask>*>(msg->pdata);
@@ -949,6 +996,50 @@ void Thread::QueuedTaskHandler::OnMessage(Message* msg) {
task.release();
}
+void Thread::AllowInvokesToThread(Thread* thread) {
+#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
+ if (!IsCurrent()) {
+ PostTask(webrtc::ToQueuedTask(
+ [thread, this]() { AllowInvokesToThread(thread); }));
+ return;
+ }
+ RTC_DCHECK_RUN_ON(this);
+ allowed_threads_.push_back(thread);
+ invoke_policy_enabled_ = true;
+#endif
+}
+
+void Thread::DisallowAllInvokes() {
+#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
+ if (!IsCurrent()) {
+ PostTask(webrtc::ToQueuedTask([this]() { DisallowAllInvokes(); }));
+ return;
+ }
+ RTC_DCHECK_RUN_ON(this);
+ allowed_threads_.clear();
+ invoke_policy_enabled_ = true;
+#endif
+}
+
+// Returns true if no policies added or if there is at least one policy
+// that permits invocation to |target| thread.
+bool Thread::IsInvokeToThreadAllowed(rtc::Thread* target) {
+#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
+ RTC_DCHECK_RUN_ON(this);
+ if (!invoke_policy_enabled_) {
+ return true;
+ }
+ for (const auto* thread : allowed_threads_) {
+ if (thread == target) {
+ return true;
+ }
+ }
+ return false;
+#else
+ return true;
+#endif
+}
+
void Thread::PostTask(std::unique_ptr<webrtc::QueuedTask> task) {
// Though Post takes MessageData by raw pointer (last parameter), it still
// takes it with ownership.
diff --git a/chromium/third_party/webrtc/rtc_base/thread.h b/chromium/third_party/webrtc/rtc_base/thread.h
index 74aab623c87..341f94285bc 100644
--- a/chromium/third_party/webrtc/rtc_base/thread.h
+++ b/chromium/third_party/webrtc/rtc_base/thread.h
@@ -338,6 +338,19 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
InvokeInternal(posted_from, functor);
}
+ // Allows invoke to specified |thread|. Thread never will be dereferenced and
+ // will be used only for reference-based comparison, so instance can be safely
+ // deleted. If NDEBUG is defined and DCHECK_ALWAYS_ON is undefined do nothing.
+ void AllowInvokesToThread(Thread* thread);
+
+ // If NDEBUG is defined and DCHECK_ALWAYS_ON is undefined do nothing.
+ void DisallowAllInvokes();
+ // Returns true if |target| was allowed by AllowInvokesToThread() or if no
+ // calls were made to AllowInvokesToThread and DisallowAllInvokes. Otherwise
+ // returns false.
+ // If NDEBUG is defined and DCHECK_ALWAYS_ON is undefined always returns true.
+ bool IsInvokeToThreadAllowed(rtc::Thread* target);
+
// Posts a task to invoke the functor on |this| thread asynchronously, i.e.
// without blocking the thread that invoked PostTask(). Ownership of |functor|
// is passed and (usually, see below) destroyed on |this| thread after it is
@@ -524,6 +537,7 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
private:
class QueuedTaskHandler final : public MessageHandler {
public:
+ QueuedTaskHandler() : MessageHandler(false) {}
void OnMessage(Message* msg) override;
};
@@ -551,6 +565,12 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
void InvokeInternal(const Location& posted_from,
rtc::FunctionView<void()> functor);
+ // Called by the ThreadManager when being set as the current thread.
+ void EnsureIsCurrentTaskQueue();
+
+ // Called by the ThreadManager when being unset as the current thread.
+ void ClearCurrentTaskQueue();
+
// Returns a static-lifetime MessageHandler which runs message with
// MessageLikeTask payload data.
static MessageHandler* GetPostTaskMessageHandler();
@@ -560,6 +580,10 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
MessageList messages_ RTC_GUARDED_BY(crit_);
PriorityQueue delayed_messages_ RTC_GUARDED_BY(crit_);
uint32_t delayed_next_num_ RTC_GUARDED_BY(crit_);
+#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
+ std::vector<Thread*> allowed_threads_ RTC_GUARDED_BY(this);
+ bool invoke_policy_enabled_ RTC_GUARDED_BY(this) = false;
+#endif
CriticalSection crit_;
bool fInitialized_;
bool fDestroyed_;
@@ -595,6 +619,8 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
// Runs webrtc::QueuedTask posted to the Thread.
QueuedTaskHandler queued_task_handler_;
+ std::unique_ptr<TaskQueueBase::CurrentTaskQueueSetter>
+ task_queue_registration_;
friend class ThreadManager;
@@ -604,7 +630,9 @@ class RTC_LOCKABLE RTC_EXPORT Thread : public webrtc::TaskQueueBase {
// AutoThread automatically installs itself at construction
// uninstalls at destruction, if a Thread object is
// _not already_ associated with the current OS thread.
-
+//
+// NOTE: *** This class should only be used by tests ***
+//
class AutoThread : public Thread {
public:
AutoThread();
diff --git a/chromium/third_party/webrtc/rtc_base/thread_unittest.cc b/chromium/third_party/webrtc/rtc_base/thread_unittest.cc
index d53a3879141..193819c6e40 100644
--- a/chromium/third_party/webrtc/rtc_base/thread_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/thread_unittest.cc
@@ -94,7 +94,7 @@ class SocketClient : public TestGenerator, public sigslot::has_slots<> {
};
// Receives messages and sends on a socket.
-class MessageClient : public MessageHandler, public TestGenerator {
+class MessageClient : public MessageHandlerAutoCleanup, public TestGenerator {
public:
MessageClient(Thread* pth, Socket* socket) : socket_(socket) {}
@@ -516,7 +516,7 @@ TEST_F(ThreadQueueTest, DisposeNotLocked) {
EXPECT_FALSE(was_locked);
}
-class DeletedMessageHandler : public MessageHandler {
+class DeletedMessageHandler : public MessageHandlerAutoCleanup {
public:
explicit DeletedMessageHandler(bool* deleted) : deleted_(deleted) {}
~DeletedMessageHandler() override { *deleted_ = true; }
@@ -606,12 +606,13 @@ TEST(ThreadManager, ProcessAllMessageQueuesWithClearedQueue) {
ThreadManager::ProcessAllMessageQueuesForTesting();
}
-class RefCountedHandler : public MessageHandler, public rtc::RefCountInterface {
+class RefCountedHandler : public MessageHandlerAutoCleanup,
+ public rtc::RefCountInterface {
public:
void OnMessage(Message* msg) override {}
};
-class EmptyHandler : public MessageHandler {
+class EmptyHandler : public MessageHandlerAutoCleanup {
public:
void OnMessage(Message* msg) override {}
};
@@ -1148,6 +1149,18 @@ TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
EXPECT_TRUE(fourth.Wait(0));
}
+TEST(ThreadPostDelayedTaskTest, IsCurrentTaskQueue) {
+ auto current_tq = webrtc::TaskQueueBase::Current();
+ {
+ std::unique_ptr<rtc::Thread> thread(rtc::Thread::Create());
+ thread->WrapCurrent();
+ EXPECT_EQ(webrtc::TaskQueueBase::Current(),
+ static_cast<webrtc::TaskQueueBase*>(thread.get()));
+ thread->UnwrapCurrent();
+ }
+ EXPECT_EQ(webrtc::TaskQueueBase::Current(), current_tq);
+}
+
class ThreadFactory : public webrtc::TaskQueueFactory {
public:
std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
diff --git a/chromium/third_party/webrtc/rtc_base/virtual_socket_server.h b/chromium/third_party/webrtc/rtc_base/virtual_socket_server.h
index f45fabf0af1..5ad66a8d34e 100644
--- a/chromium/third_party/webrtc/rtc_base/virtual_socket_server.h
+++ b/chromium/third_party/webrtc/rtc_base/virtual_socket_server.h
@@ -304,7 +304,7 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> {
// Implements the socket interface using the virtual network. Packets are
// passed as messages using the message queue of the socket server.
class VirtualSocket : public AsyncSocket,
- public MessageHandler,
+ public MessageHandlerAutoCleanup,
public sigslot::has_slots<> {
public:
VirtualSocket(VirtualSocketServer* server, int family, int type, bool async);
diff --git a/chromium/third_party/webrtc/rtc_base/virtual_socket_unittest.cc b/chromium/third_party/webrtc/rtc_base/virtual_socket_unittest.cc
index b274b40857d..78003f5cb24 100644
--- a/chromium/third_party/webrtc/rtc_base/virtual_socket_unittest.cc
+++ b/chromium/third_party/webrtc/rtc_base/virtual_socket_unittest.cc
@@ -53,7 +53,7 @@ using webrtc::testing::SSE_WRITE;
using webrtc::testing::StreamSink;
// Sends at a constant rate but with random packet sizes.
-struct Sender : public MessageHandler {
+struct Sender : public MessageHandlerAutoCleanup {
Sender(Thread* th, AsyncSocket* s, uint32_t rt)
: thread(th),
socket(std::make_unique<AsyncUDPSocket>(s)),
@@ -99,7 +99,8 @@ struct Sender : public MessageHandler {
char dummy[4096];
};
-struct Receiver : public MessageHandler, public sigslot::has_slots<> {
+struct Receiver : public MessageHandlerAutoCleanup,
+ public sigslot::has_slots<> {
Receiver(Thread* th, AsyncSocket* s, uint32_t bw)
: thread(th),
socket(std::make_unique<AsyncUDPSocket>(s)),