HRTFDatabaseLoader.h (5433B)
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 #ifndef HRTFDatabaseLoader_h 30 #define HRTFDatabaseLoader_h 31 32 #include "HRTFDatabase.h" 33 #include "mozilla/MemoryReporting.h" 34 #include "mozilla/Mutex.h" 35 #include "nsHashKeys.h" 36 37 template <class EntryType> 38 class nsTHashtable; 39 template <class T> 40 class nsAutoRef; 41 42 namespace WebCore { 43 44 // HRTFDatabaseLoader will asynchronously load the default HRTFDatabase in a new 45 // thread. 46 47 class HRTFDatabaseLoader { 48 public: 49 // Lazily creates a HRTFDatabaseLoader (if not already created) for the given 50 // sample-rate and starts loading asynchronously (when created the first 51 // time). Returns the HRTFDatabaseLoader. Must be called from the main thread. 52 static already_AddRefed<HRTFDatabaseLoader> 53 createAndLoadAsynchronouslyIfNecessary(float sampleRate); 54 55 // AddRef and Release may be called from any thread. 56 void AddRef() { 57 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) 58 int count = 59 #endif 60 ++m_refCnt; 61 MOZ_ASSERT(count > 0, "invalid ref count"); 62 NS_LOG_ADDREF(this, count, "HRTFDatabaseLoader", sizeof(*this)); 63 } 64 65 void Release() { 66 // The last reference can't be removed on a non-main thread because 67 // the object can be accessed on the main thread from the hash 68 // table via createAndLoadAsynchronouslyIfNecessary(). 69 int count = m_refCnt; 70 MOZ_ASSERT(count > 0, "extra release"); 71 // Optimization attempt to possibly skip proxying the release to the 72 // main thread. 73 if (count != 1 && m_refCnt.compareExchange(count, count - 1)) { 74 NS_LOG_RELEASE(this, count - 1, "HRTFDatabaseLoader"); 75 return; 76 } 77 78 ProxyRelease(); 79 } 80 81 // Returns true once the default database has been completely loaded. 82 bool isLoaded() const; 83 84 // waitForLoaderThreadCompletion() may be called more than once, 85 // on any thread except m_databaseLoaderThread. 86 void waitForLoaderThreadCompletion(); 87 88 HRTFDatabase* database() { 89 if (!m_databaseLoaded) { 90 return nullptr; 91 } 92 return m_hrtfDatabase.get(); 93 } 94 95 float databaseSampleRate() const { return m_databaseSampleRate; } 96 97 static void shutdown(); 98 99 // Called in asynchronous loading thread. 100 void load(); 101 102 // Sums the size of all cached database loaders. 103 static size_t sizeOfLoaders(mozilla::MallocSizeOf aMallocSizeOf); 104 105 private: 106 // Both constructor and destructor must be called from the main thread. 107 explicit HRTFDatabaseLoader(float sampleRate); 108 ~HRTFDatabaseLoader(); 109 110 size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 111 112 void ProxyRelease(); // any thread 113 void MainThreadRelease(); // main thread only 114 class ProxyReleaseEvent; 115 116 // If it hasn't already been loaded, creates a new thread and initiates 117 // asynchronous loading of the default database. This must be called from the 118 // main thread. 119 void loadAsynchronously(); 120 121 // Map from sample-rate to loader. 122 class LoaderByRateEntry : public nsFloatHashKey { 123 public: 124 explicit LoaderByRateEntry(KeyTypePointer aKey) 125 : nsFloatHashKey(aKey), 126 mLoader() // so PutEntry() will zero-initialize 127 {} 128 129 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { 130 return mLoader ? mLoader->sizeOfIncludingThis(aMallocSizeOf) : 0; 131 } 132 133 // The HRTFDatabaseLoader removes itself from s_loaderMap on destruction. 134 HRTFDatabaseLoader* MOZ_NON_OWNING_REF mLoader; 135 }; 136 137 // Keeps track of loaders on a per-sample-rate basis. 138 static nsTHashtable<LoaderByRateEntry>* s_loaderMap; // singleton 139 140 mozilla::Atomic<int> m_refCnt; 141 142 nsAutoRef<HRTFDatabase> m_hrtfDatabase; 143 144 // Holding a m_threadLock is required when accessing m_databaseLoaderThread. 145 mozilla::Mutex m_threadLock; 146 PRThread* m_databaseLoaderThread MOZ_GUARDED_BY(m_threadLock); 147 148 float m_databaseSampleRate; 149 mozilla::Atomic<bool> m_databaseLoaded; 150 }; 151 152 } // namespace WebCore 153 154 #endif // HRTFDatabaseLoader_h