Bug 1860954 don't store the graph lookup key in the graphs hashtable r=padenot,pehrsons

The necessary values for the lookup are now all in the graph itself.

I suspect this would also be possible with nsTHashtable but HashSet is
designed for a lookup class that differs from the stored class and requires
less boilerplate.

Depends on D191831

Differential Revision: https://phabricator.services.mozilla.com/D191832
This commit is contained in:
Karl Tomlinson 2023-10-26 03:42:04 +00:00
Родитель 9956d39635
Коммит 89c28e8c37
1 изменённых файлов: 59 добавлений и 59 удалений

Просмотреть файл

@ -120,29 +120,34 @@ namespace {
* A hash table containing the graph instances, one per Window ID, * A hash table containing the graph instances, one per Window ID,
* sample rate, and device ID combination. * sample rate, and device ID combination.
*/ */
class GraphKey final { struct GraphLookup final {
public: HashNumber Hash() const {
GraphKey(uint64_t aWindowID, TrackRate aSampleRate,
CubebUtils::AudioDeviceID aOutputDeviceID)
: mWindowID(aWindowID),
mSampleRate(aSampleRate),
mOutputDeviceID(aOutputDeviceID) {}
GraphKey(const GraphKey&) = default;
~GraphKey() = default;
bool operator==(const GraphKey& b) const {
return mWindowID == b.mWindowID && mSampleRate == b.mSampleRate &&
mOutputDeviceID == b.mOutputDeviceID;
}
PLDHashNumber Hash() const {
return HashGeneric(mWindowID, mSampleRate, mOutputDeviceID); return HashGeneric(mWindowID, mSampleRate, mOutputDeviceID);
} }
const uint64_t mWindowID;
private: const TrackRate mSampleRate;
uint64_t mWindowID; const CubebUtils::AudioDeviceID mOutputDeviceID;
TrackRate mSampleRate;
CubebUtils::AudioDeviceID mOutputDeviceID;
}; };
nsTHashMap<nsGenericHashKey<GraphKey>, MediaTrackGraphImpl*> gGraphs;
struct GraphHasher { // for HashSet
using Lookup = const GraphLookup;
static HashNumber hash(const Lookup& aLookup) { return aLookup.Hash(); }
static bool match(const MediaTrackGraphImpl* aGraph, const Lookup& aLookup) {
return aGraph->mWindowID == aLookup.mWindowID &&
aGraph->GraphRate() == aLookup.mSampleRate &&
aGraph->mOutputDeviceID == aLookup.mOutputDeviceID;
}
};
// The weak reference to the graph is removed when its last track is removed.
using GraphHashSet =
HashSet<MediaTrackGraphImpl*, GraphHasher, InfallibleAllocPolicy>;
GraphHashSet* Graphs() {
static GraphHashSet sGraphs(4); // 4 is minimum HashSet capacity
return &sGraphs;
}
} // anonymous namespace } // anonymous namespace
static void ApplyTrackDisabling(DisabledTrackMode aDisabledMode, static void ApplyTrackDisabling(DisabledTrackMode aDisabledMode,
@ -3284,8 +3289,9 @@ MediaTrackGraphImpl* MediaTrackGraphImpl::GetInstanceIfExists(
MOZ_ASSERT(NS_IsMainThread(), "Main thread only"); MOZ_ASSERT(NS_IsMainThread(), "Main thread only");
MOZ_ASSERT(aSampleRate > 0); MOZ_ASSERT(aSampleRate > 0);
GraphKey key(aWindowID, aSampleRate, aOutputDeviceID); GraphHashSet::Ptr p =
return gGraphs.Get(key); Graphs()->lookup({aWindowID, aSampleRate, aOutputDeviceID});
return p ? *p : nullptr;
} }
// Public method has an nsPIDOMWindowInner* parameter to ensure that the // Public method has an nsPIDOMWindowInner* parameter to ensure that the
@ -3313,31 +3319,31 @@ MediaTrackGraphImpl* MediaTrackGraphImpl::GetInstance(
MOZ_ASSERT(aGraphDriverRequested != OFFLINE_THREAD_DRIVER, MOZ_ASSERT(aGraphDriverRequested != OFFLINE_THREAD_DRIVER,
"Use CreateNonRealtimeInstance() for offline graphs"); "Use CreateNonRealtimeInstance() for offline graphs");
MediaTrackGraphImpl* graph = GraphHashSet* graphs = Graphs();
GetInstanceIfExists(aWindowID, aSampleRate, aOutputDeviceID); GraphHashSet::AddPtr addPtr =
graphs->lookupForAdd({aWindowID, aSampleRate, aOutputDeviceID});
if (!graph) { if (addPtr) { // graph already exists
GraphRunType runType = DIRECT_DRIVER; return *addPtr;
if (Preferences::GetBool("media.audiograph.single_thread.enabled", true)) {
runType = SINGLE_THREAD;
}
// In a real time graph, the number of output channels is determined by
// the underlying number of channel of the default audio output device, and
// capped to 8.
uint32_t channelCount =
std::min<uint32_t>(8, CubebUtils::MaxNumberOfChannels());
graph = new MediaTrackGraphImpl(aGraphDriverRequested, runType, aWindowID,
aSampleRate, channelCount, aOutputDeviceID,
aMainThread);
GraphKey key(aWindowID, aSampleRate, aOutputDeviceID);
gGraphs.InsertOrUpdate(key, graph);
LOG(LogLevel::Debug,
("Starting up MediaTrackGraph %p for window 0x%" PRIx64, graph,
aWindowID));
} }
GraphRunType runType = DIRECT_DRIVER;
if (Preferences::GetBool("media.audiograph.single_thread.enabled", true)) {
runType = SINGLE_THREAD;
}
// In a real time graph, the number of output channels is determined by
// the underlying number of channel of the default audio output device, and
// capped to 8.
uint32_t channelCount =
std::min<uint32_t>(8, CubebUtils::MaxNumberOfChannels());
MediaTrackGraphImpl* graph = new MediaTrackGraphImpl(
aGraphDriverRequested, runType, aWindowID, aSampleRate, channelCount,
aOutputDeviceID, aMainThread);
MOZ_ALWAYS_TRUE(graphs->add(addPtr, graph));
LOG(LogLevel::Debug, ("Starting up MediaTrackGraph %p for window 0x%" PRIx64,
graph, aWindowID));
return graph; return graph;
} }
@ -3549,14 +3555,9 @@ void MediaTrackGraph::AddTrack(MediaTrack* aTrack) {
MediaTrackGraphImpl* graph = static_cast<MediaTrackGraphImpl*>(this); MediaTrackGraphImpl* graph = static_cast<MediaTrackGraphImpl*>(this);
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (graph->mRealtime) { if (graph->mRealtime) {
bool found = false; GraphHashSet::Ptr p = Graphs()->lookup(
for (const auto& currentGraph : gGraphs.Values()) { {graph->mWindowID, GraphRate(), graph->mOutputDeviceID});
if (currentGraph == graph) { MOZ_DIAGNOSTIC_ASSERT(p, "Graph must not be shutting down");
found = true;
break;
}
}
MOZ_DIAGNOSTIC_ASSERT(found, "Graph must not be shutting down");
} }
#endif #endif
NS_ADDREF(aTrack); NS_ADDREF(aTrack);
@ -3574,12 +3575,11 @@ void MediaTrackGraphImpl::RemoveTrack(MediaTrack* aTrack) {
this, aTrack)); this, aTrack));
if (mRealtime) { if (mRealtime) {
// Find the graph in the hash table and remove it. // Find the graph in the hash table and remove it.
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) { GraphHashSet* graphs = Graphs();
if (iter.UserData() == this) { GraphHashSet::Ptr p =
iter.Remove(); graphs->lookup({mWindowID, mSampleRate, mOutputDeviceID});
break; MOZ_ASSERT(*p == this);
} graphs->remove(p);
}
} }
// The graph thread will shut itself down soon, but won't be able to do // The graph thread will shut itself down soon, but won't be able to do
// that if JS continues to run. // that if JS continues to run.