summaryrefslogtreecommitdiffstats
path: root/dom/media/CallbackThreadRegistry.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/CallbackThreadRegistry.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/dom/media/CallbackThreadRegistry.cpp b/dom/media/CallbackThreadRegistry.cpp
new file mode 100644
index 0000000000..f4d2af5bd1
--- /dev/null
+++ b/dom/media/CallbackThreadRegistry.cpp
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CallbackThreadRegistry.h"
+#include "mozilla/ClearOnShutdown.h"
+
+namespace mozilla {
+struct CallbackThreadRegistrySingleton {
+ CallbackThreadRegistrySingleton()
+ : mRegistry(MakeUnique<CallbackThreadRegistry>()) {
+ NS_DispatchToMainThread(
+ NS_NewRunnableFunction(__func__, [registry = &mRegistry] {
+ const auto phase = ShutdownPhase::XPCOMShutdownFinal;
+ MOZ_DIAGNOSTIC_ASSERT(!PastShutdownPhase(phase));
+ ClearOnShutdown(registry, phase);
+ }));
+ }
+
+ UniquePtr<CallbackThreadRegistry> mRegistry;
+};
+
+CallbackThreadRegistry::CallbackThreadRegistry()
+ : mThreadIds("CallbackThreadRegistry::mThreadIds") {}
+
+/* static */
+CallbackThreadRegistry* CallbackThreadRegistry::Get() {
+ static CallbackThreadRegistrySingleton sSingleton;
+ return sSingleton.mRegistry.get();
+}
+
+static bool CanLeak() {
+#ifdef NS_BUILD_REFCNT_LOGGING
+ static const bool logging =
+ getenv("XPCOM_MEM_LEAK_LOG") || getenv("XPCOM_MEM_BLOAT_LOG") ||
+ getenv("XPCOM_MEM_REFCNT_LOG") || getenv("XPCOM_MEM_ALLOC_LOG") ||
+ getenv("XPCOM_MEM_COMPTR_LOG");
+ return logging;
+#else
+ return false;
+#endif
+}
+
+void CallbackThreadRegistry::Register(ProfilerThreadId aThreadId,
+ const char* aName) {
+ if (!aThreadId.IsSpecified()) {
+ // profiler_current_thread_id is unspecified on unsupported platforms.
+ return;
+ }
+
+ if (CanLeak()) {
+ NS_WARNING(
+ "Not registering callback thread due to refcount logging; it may show "
+ "up as a leak of the TLS-backed nsThread wrapper if the thread "
+ "outlives xpcom shutdown.");
+ return;
+ }
+
+ auto threadIds = mThreadIds.Lock();
+ for (uint32_t i = 0; i < threadIds->Length(); i++) {
+ if ((*threadIds)[i].mId == aThreadId) {
+ (*threadIds)[i].mUserCount++;
+ return;
+ }
+ }
+ ThreadUserCount tuc;
+ tuc.mId = aThreadId;
+ tuc.mUserCount = 1;
+ threadIds->AppendElement(tuc);
+ PROFILER_REGISTER_THREAD(aName);
+}
+
+void CallbackThreadRegistry::Unregister(ProfilerThreadId aThreadId) {
+ if (!aThreadId.IsSpecified()) {
+ // profiler_current_thread_id is unspedified on unsupported platforms.
+ return;
+ }
+
+ if (CanLeak()) {
+ return;
+ }
+
+ auto threadIds = mThreadIds.Lock();
+ for (uint32_t i = 0; i < threadIds->Length(); i++) {
+ if ((*threadIds)[i].mId == aThreadId) {
+ MOZ_ASSERT((*threadIds)[i].mUserCount > 0);
+ (*threadIds)[i].mUserCount--;
+
+ if ((*threadIds)[i].mUserCount == 0) {
+ PROFILER_UNREGISTER_THREAD();
+ threadIds->RemoveElementAt(i);
+ }
+ return;
+ }
+ }
+ MOZ_ASSERT_UNREACHABLE("Current thread was not registered");
+}
+
+} // namespace mozilla