LCOV - code coverage report
Current view: top level - gfx/layers - AtomicRefCountedWithFinalize.h (source / functions) Hit Total Coverage
Test: output.info Lines: 28 58 48.3 %
Date: 2017-07-14 16:53:18 Functions: 10 14 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_
       7             : #define MOZILLA_ATOMICREFCOUNTEDWITHFINALIZE_H_
       8             : 
       9             : #include "mozilla/RefPtr.h"
      10             : #include "mozilla/Likely.h"
      11             : #include "MainThreadUtils.h"
      12             : #include "base/message_loop.h"
      13             : #include "base/task.h"
      14             : #include "mozilla/gfx/Logging.h"
      15             : 
      16             : #define ADDREF_MANUALLY(obj)  (obj)->AddRefManually(__FUNCTION__, __FILE__, __LINE__)
      17             : #define RELEASE_MANUALLY(obj)  (obj)->ReleaseManually(__FUNCTION__, __FILE__, __LINE__)
      18             : 
      19             : namespace mozilla {
      20             : 
      21             : template<class U>
      22             : class StaticRefPtr;
      23             : 
      24             : namespace gl {
      25             : template<typename T>
      26             : class RefSet;
      27             : 
      28             : template<typename T>
      29             : class RefQueue;
      30             : } // namespace gl
      31             : 
      32             : template<typename T>
      33             : class AtomicRefCountedWithFinalize
      34             : {
      35             : protected:
      36          18 :     explicit AtomicRefCountedWithFinalize(const char* aName)
      37             :       : mRecycleCallback(nullptr)
      38             :       , mRefCount(0)
      39             : #ifdef DEBUG
      40             :       , mSpew(false)
      41             :       , mManualAddRefs(0)
      42             :       , mManualReleases(0)
      43             : #endif
      44             : #ifdef NS_BUILD_REFCNT_LOGGING
      45          18 :       , mName(aName)
      46             : #endif
      47          18 :     {}
      48             : 
      49          12 :     ~AtomicRefCountedWithFinalize() {
      50          12 :       if (mRefCount >= 0) {
      51           0 :         gfxCriticalError() << "Deleting referenced object? " << mRefCount;
      52             :       }
      53          12 :     }
      54             : 
      55             : public:
      56             :     // Mark user classes that are considered flawless.
      57             :     template<class U>
      58             :     friend class ::mozilla::StaticRefPtr;
      59             : 
      60             :     template<class U>
      61             :     friend struct mozilla::RefPtrTraits;
      62             : 
      63             :     template<typename U>
      64             :     friend class ::mozilla::gl::RefSet;
      65             : 
      66             :     template<typename U>
      67             :     friend class ::mozilla::gl::RefQueue;
      68             : 
      69             :     //friend class mozilla::gl::SurfaceFactory;
      70             : 
      71           0 :     void AddRefManually(const char* funcName, const char* fileName, uint32_t lineNum) {
      72             : #ifdef DEBUG
      73           0 :       uint32_t count = ++mManualAddRefs;
      74           0 :       if (mSpew) {
      75           0 :         printf_stderr("AddRefManually() #%u in %s at %s:%u\n", count, funcName,
      76             :                       fileName, lineNum);
      77             :       }
      78             : #else
      79             :       (void)funcName;
      80             :       (void)fileName;
      81             :       (void)lineNum;
      82             : #endif
      83           0 :       AddRef();
      84           0 :     }
      85             : 
      86           0 :     void ReleaseManually(const char* funcName, const char* fileName, uint32_t lineNum) {
      87             : #ifdef DEBUG
      88           0 :       uint32_t count = ++mManualReleases;
      89           0 :       if (mSpew) {
      90           0 :         printf_stderr("ReleaseManually() #%u in %s at %s:%u\n", count, funcName,
      91             :                       fileName, lineNum);
      92             :       }
      93             : #else
      94             :       (void)funcName;
      95             :       (void)fileName;
      96             :       (void)lineNum;
      97             : #endif
      98           0 :       Release();
      99           0 :     }
     100             : 
     101             : private:
     102         213 :     void AddRef() {
     103         213 :       MOZ_ASSERT(mRefCount >= 0, "AddRef() during/after Finalize()/dtor.");
     104         213 :       mRefCount++;
     105         213 :       NS_LOG_ADDREF(this, mRefCount, mName, sizeof(*this));
     106         213 :     }
     107             : 
     108         205 :     void Release() {
     109         205 :       MOZ_ASSERT(mRefCount > 0, "Release() during/after Finalize()/dtor.");
     110             :       // Read mRecycleCallback early so that it does not get set to
     111             :       // deleted memory, if the object is goes away.  See bug 994903.
     112             :       // This saves us in the case where there is no callback, so that
     113             :       // we can do the "else if" below.
     114         205 :       RecycleCallback recycleCallback = mRecycleCallback;
     115         205 :       int currCount = --mRefCount;
     116         205 :       if (currCount < 0) {
     117           0 :         gfxCriticalError() << "Invalid reference count release" << currCount;
     118           0 :         ++mRefCount;
     119           0 :         return;
     120             :       }
     121         205 :       NS_LOG_RELEASE(this, currCount, mName);
     122             : 
     123         205 :       if (0 == currCount) {
     124          12 :         mRefCount = detail::DEAD;
     125          12 :         MOZ_ASSERT(IsDead());
     126             : 
     127             :         // Recycle listeners must call ClearRecycleCallback
     128             :         // before releasing their strong reference.
     129          12 :         if (mRecycleCallback) {
     130           0 :           gfxCriticalError() << "About to release with valid callback";
     131           0 :           mRecycleCallback = nullptr;
     132             :         }
     133             : 
     134          12 :         MOZ_ASSERT(mManualAddRefs == mManualReleases);
     135             : 
     136          12 :         T* derived = static_cast<T*>(this);
     137          12 :         derived->Finalize();
     138          12 :         delete derived;
     139         193 :       } else if (1 == currCount && recycleCallback) {
     140             :         // There is nothing enforcing this in the code, except how the callers
     141             :         // are being careful to never let the reference count go down if there
     142             :         // is a callback.
     143           0 :         MOZ_ASSERT(!IsDead());
     144           0 :         T* derived = static_cast<T*>(this);
     145           0 :         recycleCallback(derived, mClosure);
     146             :       }
     147             :     }
     148             : 
     149             : public:
     150             :     typedef void (*RecycleCallback)(T* aObject, void* aClosure);
     151             :     /**
     152             :      * Set a callback responsible for recycling this object
     153             :      * before it is finalized.
     154             :      */
     155           0 :     void SetRecycleCallback(RecycleCallback aCallback, void* aClosure)
     156             :     {
     157           0 :       MOZ_ASSERT(!IsDead());
     158           0 :       mRecycleCallback = aCallback;
     159           0 :       mClosure = aClosure;
     160           0 :     }
     161           0 :     void ClearRecycleCallback()
     162             :     {
     163           0 :       MOZ_ASSERT(!IsDead());
     164           0 :       SetRecycleCallback(nullptr, nullptr);
     165           0 :     }
     166             : 
     167             :     bool HasRecycleCallback() const
     168             :     {
     169             :       MOZ_ASSERT(!IsDead());
     170             :       return !!mRecycleCallback;
     171             :     }
     172             : 
     173          12 :     bool IsDead() const
     174             :     {
     175          12 :       return mRefCount < 0;
     176             :     }
     177             : 
     178             : private:
     179             :     RecycleCallback mRecycleCallback;
     180             :     void *mClosure;
     181             :     Atomic<int> mRefCount;
     182             : #ifdef DEBUG
     183             : public:
     184             :     bool mSpew;
     185             : private:
     186             :     Atomic<uint32_t> mManualAddRefs;
     187             :     Atomic<uint32_t> mManualReleases;
     188             : #endif
     189             : #ifdef NS_BUILD_REFCNT_LOGGING
     190             :     const char* mName;
     191             : #endif
     192             : };
     193             : 
     194             : } // namespace mozilla
     195             : 
     196             : #endif

Generated by: LCOV version 1.13