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,
* sample rate, and device ID combination.
*/
class GraphKey final {
public:
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 {
struct GraphLookup final {
HashNumber Hash() const {
return HashGeneric(mWindowID, mSampleRate, mOutputDeviceID);
}
private:
uint64_t mWindowID;
TrackRate mSampleRate;
CubebUtils::AudioDeviceID mOutputDeviceID;
const uint64_t mWindowID;
const TrackRate mSampleRate;
const 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
static void ApplyTrackDisabling(DisabledTrackMode aDisabledMode,
@ -3284,8 +3289,9 @@ MediaTrackGraphImpl* MediaTrackGraphImpl::GetInstanceIfExists(
MOZ_ASSERT(NS_IsMainThread(), "Main thread only");
MOZ_ASSERT(aSampleRate > 0);
GraphKey key(aWindowID, aSampleRate, aOutputDeviceID);
return gGraphs.Get(key);
GraphHashSet::Ptr p =
Graphs()->lookup({aWindowID, aSampleRate, aOutputDeviceID});
return p ? *p : nullptr;
}
// Public method has an nsPIDOMWindowInner* parameter to ensure that the
@ -3313,31 +3319,31 @@ MediaTrackGraphImpl* MediaTrackGraphImpl::GetInstance(
MOZ_ASSERT(aGraphDriverRequested != OFFLINE_THREAD_DRIVER,
"Use CreateNonRealtimeInstance() for offline graphs");
MediaTrackGraphImpl* graph =
GetInstanceIfExists(aWindowID, aSampleRate, aOutputDeviceID);
if (!graph) {
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());
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));
GraphHashSet* graphs = Graphs();
GraphHashSet::AddPtr addPtr =
graphs->lookupForAdd({aWindowID, aSampleRate, aOutputDeviceID});
if (addPtr) { // graph already exists
return *addPtr;
}
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;
}
@ -3549,14 +3555,9 @@ void MediaTrackGraph::AddTrack(MediaTrack* aTrack) {
MediaTrackGraphImpl* graph = static_cast<MediaTrackGraphImpl*>(this);
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (graph->mRealtime) {
bool found = false;
for (const auto& currentGraph : gGraphs.Values()) {
if (currentGraph == graph) {
found = true;
break;
}
}
MOZ_DIAGNOSTIC_ASSERT(found, "Graph must not be shutting down");
GraphHashSet::Ptr p = Graphs()->lookup(
{graph->mWindowID, GraphRate(), graph->mOutputDeviceID});
MOZ_DIAGNOSTIC_ASSERT(p, "Graph must not be shutting down");
}
#endif
NS_ADDREF(aTrack);
@ -3574,12 +3575,11 @@ void MediaTrackGraphImpl::RemoveTrack(MediaTrack* aTrack) {
this, aTrack));
if (mRealtime) {
// Find the graph in the hash table and remove it.
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
if (iter.UserData() == this) {
iter.Remove();
break;
}
}
GraphHashSet* graphs = Graphs();
GraphHashSet::Ptr p =
graphs->lookup({mWindowID, mSampleRate, mOutputDeviceID});
MOZ_ASSERT(*p == this);
graphs->remove(p);
}
// The graph thread will shut itself down soon, but won't be able to do
// that if JS continues to run.