mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
b=865241 make HRTFDatabaseLoader ref-counting thread-safe r=ehsan
--HG-- extra : rebase_source : 8cab96807c111eb103dbe931d14a86a8b97a824e
This commit is contained in:
parent
b446dda0ec
commit
1a98f66b41
@ -65,7 +65,8 @@ TemporaryRef<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronously
|
||||
}
|
||||
|
||||
HRTFDatabaseLoader::HRTFDatabaseLoader(float sampleRate)
|
||||
: m_threadLock("HRTFDatabaseLoader")
|
||||
: m_refCnt(0)
|
||||
, m_threadLock("HRTFDatabaseLoader")
|
||||
, m_databaseLoaderThread(nullptr)
|
||||
, m_databaseSampleRate(sampleRate)
|
||||
{
|
||||
@ -87,6 +88,47 @@ HRTFDatabaseLoader::~HRTFDatabaseLoader()
|
||||
}
|
||||
}
|
||||
|
||||
class HRTFDatabaseLoader::ProxyReleaseEvent MOZ_FINAL : public nsRunnable {
|
||||
public:
|
||||
explicit ProxyReleaseEvent(HRTFDatabaseLoader* loader) : mLoader(loader) {}
|
||||
NS_IMETHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
mLoader->MainThreadRelease();
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
HRTFDatabaseLoader* mLoader;
|
||||
};
|
||||
|
||||
void HRTFDatabaseLoader::ProxyRelease()
|
||||
{
|
||||
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
|
||||
if (MOZ_LIKELY(mainThread)) {
|
||||
nsRefPtr<ProxyReleaseEvent> event = new ProxyReleaseEvent(this);
|
||||
DebugOnly<nsresult> rv =
|
||||
mainThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch release event");
|
||||
} else {
|
||||
// Should be in XPCOM shutdown.
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"Main thread is not available for dispatch.");
|
||||
MainThreadRelease();
|
||||
}
|
||||
}
|
||||
|
||||
void HRTFDatabaseLoader::MainThreadRelease()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
int count = --m_refCnt;
|
||||
MOZ_ASSERT(count >= 0, "extra release");
|
||||
NS_LOG_RELEASE(this, count, "HRTFDatabaseLoader");
|
||||
if (count == 0) {
|
||||
// It is safe to delete here as the first reference can only be added
|
||||
// on this (main) thread.
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
// Asynchronously load the database in this thread.
|
||||
static void databaseLoaderEntry(void* threadData)
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace WebCore {
|
||||
|
||||
// HRTFDatabaseLoader will asynchronously load the default HRTFDatabase in a new thread.
|
||||
|
||||
class HRTFDatabaseLoader : public mozilla::RefCounted<HRTFDatabaseLoader> {
|
||||
class HRTFDatabaseLoader {
|
||||
public:
|
||||
// Lazily creates a HRTFDatabaseLoader (if not already created) for the given sample-rate
|
||||
// and starts loading asynchronously (when created the first time).
|
||||
@ -47,9 +47,34 @@ public:
|
||||
// Must be called from the main thread.
|
||||
static mozilla::TemporaryRef<HRTFDatabaseLoader> createAndLoadAsynchronouslyIfNecessary(float sampleRate);
|
||||
|
||||
// Both constructor and destructor must be called from the main thread.
|
||||
~HRTFDatabaseLoader();
|
||||
|
||||
// AddRef and Release may be called from any thread.
|
||||
void AddRef()
|
||||
{
|
||||
#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)
|
||||
int count =
|
||||
#endif
|
||||
++m_refCnt;
|
||||
MOZ_ASSERT(count > 0, "invalid ref count");
|
||||
NS_LOG_ADDREF(this, count, "HRTFDatabaseLoader", sizeof(*this));
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
// The last reference can't be removed on a non-main thread because
|
||||
// the object can be accessed on the main thread from the hash
|
||||
// table via createAndLoadAsynchronouslyIfNecessary().
|
||||
int count = m_refCnt;
|
||||
MOZ_ASSERT(count > 0, "extra release");
|
||||
// Optimization attempt to possibly skip proxying the release to the
|
||||
// main thread.
|
||||
if (count != 1 && m_refCnt.compareExchange(count, count - 1)) {
|
||||
NS_LOG_RELEASE(this, count - 1, "HRTFDatabaseLoader");
|
||||
return;
|
||||
}
|
||||
|
||||
ProxyRelease();
|
||||
}
|
||||
|
||||
// Returns true once the default database has been completely loaded.
|
||||
bool isLoaded() const;
|
||||
|
||||
@ -67,7 +92,12 @@ public:
|
||||
private:
|
||||
// Both constructor and destructor must be called from the main thread.
|
||||
explicit HRTFDatabaseLoader(float sampleRate);
|
||||
~HRTFDatabaseLoader();
|
||||
|
||||
void ProxyRelease(); // any thread
|
||||
void MainThreadRelease(); // main thread only
|
||||
class ProxyReleaseEvent;
|
||||
|
||||
// If it hasn't already been loaded, creates a new thread and initiates asynchronous loading of the default database.
|
||||
// This must be called from the main thread.
|
||||
void loadAsynchronously();
|
||||
@ -85,6 +115,8 @@ private:
|
||||
// Keeps track of loaders on a per-sample-rate basis.
|
||||
static nsTHashtable<LoaderByRateEntry> *s_loaderMap; // singleton
|
||||
|
||||
mozilla::Atomic<int> m_refCnt;
|
||||
|
||||
nsAutoRef<HRTFDatabase> m_hrtfDatabase;
|
||||
|
||||
// Holding a m_threadLock is required when accessing m_databaseLoaderThread.
|
||||
|
Loading…
Reference in New Issue
Block a user