/* * Copyright 2015, Mozilla Foundation and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __RefCount_h__ #define __RefCount_h__ #include <stdint.h> #include <assert.h> #include "ClearKeyUtils.h" #if defined(_MSC_VER) #include <atomic> typedef std::atomic<uint32_t> AtomicRefCount; #else class AtomicRefCount { public: explicit AtomicRefCount(uint32_t aValue) : mCount(aValue) , mMutex(GMPCreateMutex()) { assert(mMutex); } ~AtomicRefCount() { if (mMutex) { mMutex->Destroy(); } } uint32_t operator--() { AutoLock lock(mMutex); return --mCount; } uint32_t operator++() { AutoLock lock(mMutex); return ++mCount; } operator uint32_t() { AutoLock lock(mMutex); return mCount; } private: uint32_t mCount; GMPMutex* mMutex; }; #endif // Note: Thread safe. class RefCounted { public: void AddRef() { ++mRefCount; } uint32_t Release() { uint32_t newCount = --mRefCount; if (!newCount) { delete this; } return newCount; } protected: RefCounted() : mRefCount(0) { } virtual ~RefCounted() { assert(!mRefCount); } AtomicRefCount mRefCount; }; template<class T> class RefPtr { public: explicit RefPtr(T* aPtr) : mPtr(nullptr) { Assign(aPtr); } ~RefPtr() { Assign(nullptr); } T* operator->() const { return mPtr; } RefPtr& operator=(T* aVal) { Assign(aVal); return *this; } private: void Assign(T* aPtr) { if (mPtr) { mPtr->Release(); } mPtr = aPtr; if (mPtr) { aPtr->AddRef(); } } T* mPtr; }; #endif // __RefCount_h__