LCOV - code coverage report
Current view: top level - dom/media/webaudio/blink - HRTFDatabaseLoader.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 101 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2010 Google Inc. All rights reserved.
       3             :  *
       4             :  * Redistribution and use in source and binary forms, with or without
       5             :  * modification, are permitted provided that the following conditions
       6             :  * are met:
       7             :  *
       8             :  * 1.  Redistributions of source code must retain the above copyright
       9             :  *     notice, this list of conditions and the following disclaimer.
      10             :  * 2.  Redistributions in binary form must reproduce the above copyright
      11             :  *     notice, this list of conditions and the following disclaimer in the
      12             :  *     documentation and/or other materials provided with the distribution.
      13             :  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
      14             :  *     its contributors may be used to endorse or promote products derived
      15             :  *     from this software without specific prior written permission.
      16             :  *
      17             :  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
      18             :  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      19             :  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      20             :  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
      21             :  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      22             :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      23             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      24             :  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      26             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             :  */
      28             : 
      29             : #include "HRTFDatabaseLoader.h"
      30             : #include "HRTFDatabase.h"
      31             : #include "GeckoProfiler.h"
      32             : #include "nsThreadUtils.h"
      33             : 
      34             : using namespace mozilla;
      35             : 
      36             : namespace WebCore {
      37             : 
      38             : // Singleton
      39             : nsTHashtable<HRTFDatabaseLoader::LoaderByRateEntry>*
      40             :     HRTFDatabaseLoader::s_loaderMap = nullptr;
      41             : 
      42           0 : size_t HRTFDatabaseLoader::sizeOfLoaders(mozilla::MallocSizeOf aMallocSizeOf)
      43             : {
      44           0 :     return s_loaderMap ? s_loaderMap->SizeOfIncludingThis(aMallocSizeOf) : 0;
      45             : }
      46             : 
      47           0 : already_AddRefed<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate)
      48             : {
      49           0 :     MOZ_ASSERT(NS_IsMainThread());
      50             : 
      51           0 :     RefPtr<HRTFDatabaseLoader> loader;
      52             : 
      53           0 :     if (!s_loaderMap) {
      54           0 :         s_loaderMap = new nsTHashtable<LoaderByRateEntry>();
      55             :     }
      56             : 
      57           0 :     LoaderByRateEntry* entry = s_loaderMap->PutEntry(sampleRate);
      58           0 :     loader = entry->mLoader;
      59           0 :     if (loader) { // existing entry
      60           0 :         MOZ_ASSERT(sampleRate == loader->databaseSampleRate());
      61           0 :         return loader.forget();
      62             :     }
      63             : 
      64           0 :     loader = new HRTFDatabaseLoader(sampleRate);
      65           0 :     entry->mLoader = loader;
      66             : 
      67           0 :     loader->loadAsynchronously();
      68             : 
      69           0 :     return loader.forget();
      70             : }
      71             : 
      72           0 : HRTFDatabaseLoader::HRTFDatabaseLoader(float sampleRate)
      73             :     : m_refCnt(0)
      74             :     , m_threadLock("HRTFDatabaseLoader")
      75             :     , m_databaseLoaderThread(nullptr)
      76           0 :     , m_databaseSampleRate(sampleRate)
      77             : {
      78           0 :     MOZ_ASSERT(NS_IsMainThread());
      79           0 : }
      80             : 
      81           0 : HRTFDatabaseLoader::~HRTFDatabaseLoader()
      82             : {
      83           0 :     MOZ_ASSERT(NS_IsMainThread());
      84             : 
      85           0 :     waitForLoaderThreadCompletion();
      86           0 :     m_hrtfDatabase.reset();
      87             : 
      88           0 :     if (s_loaderMap) {
      89             :         // Remove ourself from the map.
      90           0 :         s_loaderMap->RemoveEntry(m_databaseSampleRate);
      91           0 :         if (s_loaderMap->Count() == 0) {
      92           0 :             delete s_loaderMap;
      93           0 :             s_loaderMap = nullptr;
      94             :         }
      95             :     }
      96           0 : }
      97             : 
      98           0 : size_t HRTFDatabaseLoader::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
      99             : {
     100           0 :     size_t amount = aMallocSizeOf(this);
     101             : 
     102             :     // NB: Need to make sure we're not competing with the loader thread.
     103           0 :     const_cast<HRTFDatabaseLoader*>(this)->waitForLoaderThreadCompletion();
     104             : 
     105           0 :     if (m_hrtfDatabase) {
     106           0 :         amount += m_hrtfDatabase->sizeOfIncludingThis(aMallocSizeOf);
     107             :     }
     108             : 
     109           0 :     return amount;
     110             : }
     111             : 
     112           0 : class HRTFDatabaseLoader::ProxyReleaseEvent final : public Runnable {
     113             : public:
     114           0 :   explicit ProxyReleaseEvent(HRTFDatabaseLoader* loader)
     115           0 :     : mozilla::Runnable("WebCore::HRTFDatabaseLoader::ProxyReleaseEvent")
     116           0 :     , mLoader(loader)
     117             :   {
     118           0 :   }
     119           0 :   NS_IMETHOD Run() override
     120             :   {
     121           0 :     mLoader->MainThreadRelease();
     122           0 :     return NS_OK;
     123             :     }
     124             : private:
     125             :     HRTFDatabaseLoader* mLoader;
     126             : };
     127             : 
     128           0 : void HRTFDatabaseLoader::ProxyRelease()
     129             : {
     130           0 :     nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
     131           0 :     if (MOZ_LIKELY(mainTarget)) {
     132           0 :         RefPtr<ProxyReleaseEvent> event = new ProxyReleaseEvent(this);
     133             :         DebugOnly<nsresult> rv =
     134           0 :             mainTarget->Dispatch(event, NS_DISPATCH_NORMAL);
     135           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv), "Failed to dispatch release event");
     136             :     } else {
     137             :         // Should be in XPCOM shutdown.
     138           0 :         MOZ_ASSERT(NS_IsMainThread(),
     139             :                    "Main thread is not available for dispatch.");
     140           0 :         MainThreadRelease();
     141             :     }
     142           0 : }
     143             : 
     144           0 : void HRTFDatabaseLoader::MainThreadRelease()
     145             : {
     146           0 :     MOZ_ASSERT(NS_IsMainThread());
     147           0 :     int count = --m_refCnt;
     148           0 :     MOZ_ASSERT(count >= 0, "extra release");
     149           0 :     NS_LOG_RELEASE(this, count, "HRTFDatabaseLoader");
     150           0 :     if (count == 0) {
     151             :         // It is safe to delete here as the first reference can only be added
     152             :         // on this (main) thread.
     153           0 :         delete this;
     154             :     }
     155           0 : }
     156             : 
     157             : // Asynchronously load the database in this thread.
     158           0 : static void databaseLoaderEntry(void* threadData)
     159             : {
     160           0 :     AutoProfilerRegisterThread registerThread("HRTFDatabaseLdr");
     161           0 :     NS_SetCurrentThreadName("HRTFDatabaseLdr");
     162             : 
     163           0 :     HRTFDatabaseLoader* loader = reinterpret_cast<HRTFDatabaseLoader*>(threadData);
     164           0 :     MOZ_ASSERT(loader);
     165           0 :     loader->load();
     166           0 : }
     167             : 
     168           0 : void HRTFDatabaseLoader::load()
     169             : {
     170           0 :     MOZ_ASSERT(!NS_IsMainThread());
     171           0 :     MOZ_ASSERT(!m_hrtfDatabase.get(), "Called twice");
     172             :     // Load the default HRTF database.
     173           0 :     m_hrtfDatabase = HRTFDatabase::create(m_databaseSampleRate);
     174             :     // Notifies the main thread of completion.  See loadAsynchronously().
     175           0 :     Release();
     176           0 : }
     177             : 
     178           0 : void HRTFDatabaseLoader::loadAsynchronously()
     179             : {
     180           0 :     MOZ_ASSERT(NS_IsMainThread());
     181           0 :     MOZ_ASSERT(m_refCnt, "Must not be called before a reference is added");
     182             : 
     183             :     // Add a reference so that the destructor won't run and wait for the
     184             :     // loader thread, until load() has completed.
     185           0 :     AddRef();
     186             : 
     187           0 :     MutexAutoLock locker(m_threadLock);
     188             : 
     189           0 :     MOZ_ASSERT(!m_hrtfDatabase.get() && !m_databaseLoaderThread,
     190             :                "Called twice");
     191             :     // Start the asynchronous database loading process.
     192           0 :     m_databaseLoaderThread =
     193           0 :         PR_CreateThread(PR_USER_THREAD, databaseLoaderEntry, this,
     194             :                         PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
     195             :                         PR_JOINABLE_THREAD, 0);
     196           0 : }
     197             : 
     198           0 : bool HRTFDatabaseLoader::isLoaded() const
     199             : {
     200           0 :     return m_hrtfDatabase.get();
     201             : }
     202             : 
     203           0 : void HRTFDatabaseLoader::waitForLoaderThreadCompletion()
     204             : {
     205           0 :     MutexAutoLock locker(m_threadLock);
     206             : 
     207             :     // waitForThreadCompletion() should not be called twice for the same thread.
     208           0 :     if (m_databaseLoaderThread) {
     209           0 :         DebugOnly<PRStatus> status = PR_JoinThread(m_databaseLoaderThread);
     210           0 :         MOZ_ASSERT(status == PR_SUCCESS, "PR_JoinThread failed");
     211             :     }
     212           0 :     m_databaseLoaderThread = nullptr;
     213           0 : }
     214             : 
     215           0 : void HRTFDatabaseLoader::shutdown()
     216             : {
     217           0 :     MOZ_ASSERT(NS_IsMainThread());
     218           0 :     if (s_loaderMap) {
     219             :         // Set s_loaderMap to nullptr so that the hashtable is not modified on
     220             :         // reference release during enumeration.
     221           0 :         nsTHashtable<LoaderByRateEntry>* loaderMap = s_loaderMap;
     222           0 :         s_loaderMap = nullptr;
     223           0 :         for (auto iter = loaderMap->Iter(); !iter.Done(); iter.Next()) {
     224           0 :           iter.Get()->mLoader->waitForLoaderThreadCompletion();
     225             :         }
     226           0 :         delete loaderMap;
     227             :     }
     228           0 : }
     229             : 
     230             : } // namespace WebCore

Generated by: LCOV version 1.13