diff -r 000000000000 -r 6474c204b198 gfx/layers/AtomicRefCountedWithFinalize.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/layers/AtomicRefCountedWithFinalize.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_ +#define MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_ + +#include "mozilla/RefPtr.h" +#include "mozilla/NullPtr.h" + +namespace mozilla { + +template +class AtomicRefCountedWithFinalize +{ + protected: + AtomicRefCountedWithFinalize() + : mRecycleCallback(nullptr) + , mRefCount(0) + {} + + ~AtomicRefCountedWithFinalize() {} + + public: + void AddRef() { + MOZ_ASSERT(mRefCount >= 0); + ++mRefCount; + } + + void Release() { + MOZ_ASSERT(mRefCount > 0); + // Read mRecycleCallback early so that it does not get set to + // deleted memory, if the object is goes away. + RecycleCallback recycleCallback = mRecycleCallback; + int currCount = --mRefCount; + if (0 == currCount) { + // Recycle listeners must call ClearRecycleCallback + // before releasing their strong reference. + MOZ_ASSERT(mRecycleCallback == nullptr); +#ifdef DEBUG + mRefCount = detail::DEAD; +#endif + T* derived = static_cast(this); + derived->Finalize(); + delete derived; + } else if (1 == currCount && recycleCallback) { + T* derived = static_cast(this); + recycleCallback(derived, mClosure); + } + } + + typedef void (*RecycleCallback)(T* aObject, void* aClosure); + /** + * Set a callback responsible for recycling this object + * before it is finalized. + */ + void SetRecycleCallback(RecycleCallback aCallback, void* aClosure) + { + mRecycleCallback = aCallback; + mClosure = aClosure; + } + void ClearRecycleCallback() { SetRecycleCallback(nullptr, nullptr); } + +private: + RecycleCallback mRecycleCallback; + void *mClosure; + Atomic mRefCount; +}; + +} + +#endif