1 /* 2 * Copyright 2015, Mozilla Foundation and contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef __RefCount_h__ 18 #define __RefCount_h__ 19 20 #include <stdint.h> 21 #include <assert.h> 22 23 extern GMPPlatformAPI* g_platform_api; 24 GMPCreateMutex()25inline GMPMutex* GMPCreateMutex() { 26 GMPMutex* mutex; 27 if (!g_platform_api) { 28 return nullptr; 29 } 30 GMPErr err = g_platform_api->createmutex(&mutex); 31 assert(mutex); 32 return GMP_FAILED(err) ? nullptr : mutex; 33 } 34 35 class AutoLock { 36 public: AutoLock(GMPMutex * aMutex)37 explicit AutoLock(GMPMutex* aMutex) 38 : mMutex(aMutex) 39 { 40 assert(aMutex); 41 if (mMutex) { 42 mMutex->Acquire(); 43 } 44 } ~AutoLock()45 ~AutoLock() { 46 if (mMutex) { 47 mMutex->Release(); 48 } 49 } 50 private: 51 GMPMutex* mMutex; 52 }; 53 54 class AtomicRefCount { 55 public: AtomicRefCount(uint32_t aValue)56 explicit AtomicRefCount(uint32_t aValue) 57 : mCount(aValue) 58 , mMutex(GMPCreateMutex()) 59 { 60 assert(mMutex); 61 } ~AtomicRefCount()62 ~AtomicRefCount() 63 { 64 if (mMutex) { 65 mMutex->Destroy(); 66 } 67 } 68 uint32_t operator--() { 69 AutoLock lock(mMutex); 70 return --mCount; 71 } 72 uint32_t operator++() { 73 AutoLock lock(mMutex); 74 return ++mCount; 75 } uint32_t()76 operator uint32_t() { 77 AutoLock lock(mMutex); 78 return mCount; 79 } 80 private: 81 uint32_t mCount; 82 GMPMutex* mMutex; 83 }; 84 85 // Note: Thread safe. 86 class RefCounted { 87 public: AddRef()88 void AddRef() { 89 ++mRefCount; 90 } 91 Release()92 uint32_t Release() { 93 uint32_t newCount = --mRefCount; 94 if (!newCount) { 95 delete this; 96 } 97 return newCount; 98 } 99 100 protected: RefCounted()101 RefCounted() 102 : mRefCount(0) 103 { 104 } ~RefCounted()105 virtual ~RefCounted() 106 { 107 assert(!mRefCount); 108 } 109 AtomicRefCount mRefCount; 110 }; 111 112 template<class T> 113 class RefPtr { 114 public: RefPtr(T * aPtr)115 explicit RefPtr(T* aPtr) : mPtr(nullptr) { 116 Assign(aPtr); 117 } ~RefPtr()118 ~RefPtr() { 119 Assign(nullptr); 120 } 121 T* operator->() const { return mPtr; } 122 123 RefPtr& operator=(T* aVal) { 124 Assign(aVal); 125 return *this; 126 } 127 128 private: Assign(T * aPtr)129 void Assign(T* aPtr) { 130 if (mPtr) { 131 mPtr->Release(); 132 } 133 mPtr = aPtr; 134 if (mPtr) { 135 aPtr->AddRef(); 136 } 137 } 138 T* mPtr; 139 }; 140 141 #endif // __RefCount_h__ 142