Bug 1646348 - Introduce the AudioThreadRegistry. r=achronop
authorPaul Adenot <paul@paul.cx>
Tue, 23 Jun 2020 16:43:09 +0000
changeset 536934 26806d0019274e7b21d40a95accdc8c263805b5a
parent 536933 6e30d79d7bf50b6b508f1653ff79f569c8990642
child 536935 40b5b4babc734ba305d8d1c864e06767aa0f4167
push id37533
push userdluca@mozilla.com
push dateTue, 23 Jun 2020 21:38:40 +0000
treeherdermozilla-central@d48aa0f0aa0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersachronop
bugs1646348
milestone79.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1646348 - Introduce the AudioThreadRegistry. r=achronop This keeps track of how many users of an audio thread there is, and takes care of registring or unregistring those threads to the Gecko Profiler. Differential Revision: https://phabricator.services.mozilla.com/D80464
dom/media/AudioThreadRegistry.h
dom/media/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/media/AudioThreadRegistry.h
@@ -0,0 +1,83 @@
+/* -*- 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/. */
+
+#ifndef AUDIOTHREADREGISTRY_H
+#define AUDIOTHREADREGISTRY_H
+
+#include <cstdint>
+#include <mozilla/DataMutex.h>
+#include <nsTArray.h>
+#include <thread>
+#include <GeckoProfiler.h>
+
+namespace mozilla {
+
+// This class is a singleton that tracks all audio callback threads and makes
+// sure they are registered or unregistered to the profiler safely and
+// consistently.
+//
+// Register and Unregister are fairly expensive and shouldn't be used in a hot
+// path.
+class AudioThreadRegistry final {
+ public:
+  AudioThreadRegistry() : mThreadIds("AudioThreadId") {}
+  ~AudioThreadRegistry() {
+    // It would be nice to be able to assert that all threads have be
+    // unregistered, but we can't: it's legal to suspend an audio stream, so
+    // that the callback isn't called, and then immediately destroy it.
+  }
+
+  // This is intended to be called when an object starts an audio callback
+  // thread.
+  void Register(int aThreadId) {
+    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("NativeAudioCallback");
+  }
+
+  // This is intended to be called when an object stops an audio callback thread
+  void Unregister(int aThreadId) {
+    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(false);
+  }
+
+ private:
+  AudioThreadRegistry(const AudioThreadRegistry&) = delete;
+  AudioThreadRegistry& operator=(const AudioThreadRegistry&) = delete;
+  AudioThreadRegistry(AudioThreadRegistry&&) = delete;
+  AudioThreadRegistry& operator=(AudioThreadRegistry&&) = delete;
+
+  struct ThreadUserCount {
+    int mId;  // from profiler_current_thread_id
+    int mUserCount;
+  };
+  DataMutex<nsTArray<ThreadUserCount>> mThreadIds;
+};
+
+}  // namespace mozilla
+
+#endif  // AUDIOTHREADREGISTRY_H
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -112,16 +112,17 @@ EXPORTS += [
     'AudioDeviceInfo.h',
     'AudioDriftCorrection.h',
     'AudioMixer.h',
     'AudioPacketizer.h',
     'AudioRingBuffer.h',
     'AudioSampleFormat.h',
     'AudioSegment.h',
     'AudioStream.h',
+    'AudioThreadRegistry.h',
     'AutoplayPolicy.h',
     'BackgroundVideoDecodingPermissionObserver.h',
     'Benchmark.h',
     'BitReader.h',
     'BitWriter.h',
     'BufferMediaResource.h',
     'BufferReader.h',
     'ByteWriter.h',