• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()25 inline 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