diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/core/SkInstCnt.h | 183 | ||||
-rw-r--r-- | include/core/SkPath.h | 2 | ||||
-rw-r--r-- | include/core/SkRefCnt.h | 2 | ||||
-rw-r--r-- | include/core/SkStream.h | 2 | ||||
-rw-r--r-- | include/gpu/GrGpuResource.h | 4 | ||||
-rw-r--r-- | include/gpu/GrGpuResourceRef.h | 4 | ||||
-rw-r--r-- | include/gpu/GrProgramElement.h | 2 | ||||
-rw-r--r-- | include/gpu/GrTextureAccess.h | 2 |
8 files changed, 67 insertions, 134 deletions
diff --git a/include/core/SkInstCnt.h b/include/core/SkInstCnt.h index e4b43d130b..8aeb14ec1a 100644 --- a/include/core/SkInstCnt.h +++ b/include/core/SkInstCnt.h @@ -5,143 +5,76 @@ * found in the LICENSE file. */ - #ifndef SkInstCnt_DEFINED #define SkInstCnt_DEFINED -/* - * The instance counting system consists of three macros that create the - * instance counting machinery. A class is added to the system by adding: - * SK_DECLARE_INST_COUNT at the top of its declaration for derived classes - * SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class - * At the end of an application a call to all the "root" objects' - * CheckInstanceCount methods should be made +/* To count all instances of T, including all subclasses of T, + * add SK_DECLARE_INST_COUNT(T) to T's class definition. + * If you want to print out counts of leaked instances, set gPrintInstCount to true in main(). + * + * E.g. + * struct Base { SK_DECLARE_INST_COUNT(Base) }; + * struct A : public Base {}; + * struct SubBase : public Base { SK_DECLARE_INST_COUNT(SubBase); } + * struct B : public SubBase {}; + * + * If gPrintInstCount is true, at the program exit you will see something like: + * Base: <N> leaked instances + * SubBase: <M> leaked instances + * where N >= M. Leaked instances of A count against Base; leaked instances of B count against + * both SubBase and Base. + * + * If SK_ENABLE_INST_COUNT is not defined or defined to 0, or we're in a shared library build, + * this entire system is compiled away to a noop. */ + #include "SkTypes.h" -#if SK_ENABLE_INST_COUNT -// Static variables inside member functions below may be defined multiple times -// if Skia is being used as a dynamic library. Instance counting should be on -// only for static builds. See bug skia:2058. -#if defined(SKIA_DLL) -#error Instance counting works only when Skia is built as a static library. -#endif +#if SK_ENABLE_INST_COUNT && !defined(SKIA_DLL) // See skia:2058 for why we noop on shared builds. + #include "SkThread.h" + #include <stdlib.h> + + #define SK_DECLARE_INST_COUNT(T) \ + static const char* InstCountClassName() { return #T; } \ + SkInstCount<T, T::InstCountClassName> fInstCnt; \ + static int32_t GetInstanceCount() { return SkInstCount<T, InstCountClassName>::Count(); } + + extern bool gPrintInstCount; -#include "SkOnce.h" -#include "SkTArray.h" -#include "SkThread.h" -extern bool gPrintInstCount; + template <typename T, const char*(Name)()> + class SkInstCount { + public: + SkInstCount() { Inc(); } + SkInstCount(const SkInstCount&) { Inc(); } + ~SkInstCount() { sk_atomic_dec(&gCount); } -// The non-root classes just register themselves with their parent -#define SK_DECLARE_INST_COUNT(className) \ - SK_DECLARE_INST_COUNT_INTERNAL(className, \ - INHERITED::AddInstChild(CheckInstanceCount);) + SkInstCount& operator==(const SkInstCount&) { return *this; } // == can't change the count. -// The root classes registers a function to print out the memory stats when -// the app ends -#define SK_DECLARE_INST_COUNT_ROOT(className) \ - SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) + static void Inc() { + // If it's the first time we go from 0 to 1, register to print leaks at process exit. + if (0 == sk_atomic_inc(&gCount) && sk_atomic_cas(&gRegistered, 0, 1)) { + atexit(PrintAtExit); + } + } -#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ - class SkInstanceCountHelper { \ - public: \ - SkInstanceCountHelper() { \ - SK_DECLARE_STATIC_ONCE(once); \ - SkOnce(&once, init); \ - sk_atomic_inc(GetInstanceCountPtr()); \ - } \ - \ - static void init() { \ - initStep \ - } \ - \ - SkInstanceCountHelper(const SkInstanceCountHelper&) { \ - sk_atomic_inc(GetInstanceCountPtr()); \ - } \ - \ - ~SkInstanceCountHelper() { \ - sk_atomic_dec(GetInstanceCountPtr()); \ - } \ - \ - static int32_t* GetInstanceCountPtr() { \ - static int32_t gInstanceCount; \ - return &gInstanceCount; \ - } \ - \ - static SkTArray<int (*)(int, bool)>*& GetChildren() { \ - static SkTArray<int (*)(int, bool)>* gChildren; \ - return gChildren; \ - } \ - \ - static void create_mutex(SkMutex** mutex) { \ - *mutex = SkNEW(SkMutex); \ - } \ - static SkBaseMutex& GetChildrenMutex() { \ - static SkMutex* childrenMutex; \ - SK_DECLARE_STATIC_ONCE(once); \ - SkOnce(&once, className::SkInstanceCountHelper::create_mutex, &childrenMutex);\ - return *childrenMutex; \ - } \ - \ - } fInstanceCountHelper; \ - \ - static int32_t GetInstanceCount() { \ - return *SkInstanceCountHelper::GetInstanceCountPtr(); \ - } \ - \ - static void exitPrint() { \ - CheckInstanceCount(0, true); \ - } \ - \ - static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ - if (gPrintInstCount && 0 != GetInstanceCount()) { \ - SkDebugf("%*c Leaked %s: %d\n", \ - 4*level, ' ', #className, \ - GetInstanceCount()); \ - } \ - if (NULL == SkInstanceCountHelper::GetChildren()) { \ - return GetInstanceCount(); \ - } \ - SkTArray<int (*)(int, bool)>* children = \ - SkInstanceCountHelper::GetChildren(); \ - int childCount = children->count(); \ - int count = GetInstanceCount(); \ - for (int i = 0; i < childCount; ++i) { \ - count -= (*(*children)[i])(level+1, cleanUp); \ - } \ - SkASSERT(count >= 0); \ - if (gPrintInstCount && childCount > 0 && count > 0) { \ - SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ - } \ - if (cleanUp) { \ - delete children; \ - SkInstanceCountHelper::GetChildren() = NULL; \ - } \ - return GetInstanceCount(); \ - } \ - \ - static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ - if (CheckInstanceCount != childCheckInstCnt) { \ - SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \ - if (NULL == SkInstanceCountHelper::GetChildren()) { \ - SkInstanceCountHelper::GetChildren() = \ - new SkTArray<int (*)(int, bool)>; \ - } \ - SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \ - } \ - } + static void PrintAtExit() { + int32_t leaks = Count(); + if (gPrintInstCount && leaks > 0) { + SkDebugf("Leaked %s: %d\n", Name(), leaks); + } + } + // FIXME: Used publicly by unit tests. Seems like a bad idea in a DM world. + static int32_t Count() { return sk_acquire_load(&gCount); } + + private: + static int32_t gCount, gRegistered; + }; + // As template values, these will be deduplicated. (No one-definition rule problems.) + template <typename T, const char*(Name)()> int32_t SkInstCount<T, Name>::gCount = 0; + template <typename T, const char*(Name)()> int32_t SkInstCount<T, Name>::gRegistered = 0; #else -// Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by -// causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays -// compiling. -#define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); } -#define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } + #define SK_DECLARE_INST_COUNT(T) #endif -// Following are deprecated. They are defined only for backwards API compatibility. -#define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className) -#define SK_DEFINE_INST_COUNT(className) -#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) - #endif // SkInstCnt_DEFINED diff --git a/include/core/SkPath.h b/include/core/SkPath.h index f895f7fe24..2fe332f3c4 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -30,7 +30,7 @@ class SkWStream; */ class SK_API SkPath { public: - SK_DECLARE_INST_COUNT_ROOT(SkPath); + SK_DECLARE_INST_COUNT(SkPath); SkPath(); SkPath(const SkPath&); diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h index 5d394f0c2a..cf3e385b25 100644 --- a/include/core/SkRefCnt.h +++ b/include/core/SkRefCnt.h @@ -27,7 +27,7 @@ */ class SK_API SkRefCntBase : SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(SkRefCntBase) + SK_DECLARE_INST_COUNT(SkRefCntBase) /** Default construct, initializing the reference count to 1. */ diff --git a/include/core/SkStream.h b/include/core/SkStream.h index 2d5969853a..abd9f92403 100644 --- a/include/core/SkStream.h +++ b/include/core/SkStream.h @@ -170,7 +170,7 @@ public: class SK_API SkWStream : SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(SkWStream) + SK_DECLARE_INST_COUNT(SkWStream) virtual ~SkWStream(); diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h index 8c888410bf..4340f710b3 100644 --- a/include/gpu/GrGpuResource.h +++ b/include/gpu/GrGpuResource.h @@ -22,7 +22,7 @@ class GrResourceCache2; * Base class for GrGpuResource. Handles the various types of refs we need. Separated out as a base * class to isolate the ref-cnting behavior and provide friendship without exposing all of * GrGpuResource. - * + * * Gpu resources can have three types of refs: * 1) Normal ref (+ by ref(), - by unref()): These are used by code that is issuing draw calls * that read and write the resource via GrDrawTarget and by any object that must own a @@ -40,7 +40,7 @@ class GrResourceCache2; */ template <typename DERIVED> class GrIORef : public SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(GrIORef) + SK_DECLARE_INST_COUNT(GrIORef) // Some of the signatures are written to mirror SkRefCnt so that GrGpuResource can work with // templated helper classes (e.g. SkAutoTUnref). However, we have different categories of diff --git a/include/gpu/GrGpuResourceRef.h b/include/gpu/GrGpuResourceRef.h index 0e23eeab61..b8ba334ff3 100644 --- a/include/gpu/GrGpuResourceRef.h +++ b/include/gpu/GrGpuResourceRef.h @@ -36,7 +36,7 @@ */ class GrGpuResourceRef : SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(GrGpuResourceRef); + SK_DECLARE_INST_COUNT(GrGpuResourceRef); ~GrGpuResourceRef(); @@ -87,7 +87,7 @@ private: typedef SkNoncopyable INHERITED; }; -/** +/** * Templated version of GrGpuResourceRef to enforce type safety. */ template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { diff --git a/include/gpu/GrProgramElement.h b/include/gpu/GrProgramElement.h index e1adcc31f7..5ebf150a84 100644 --- a/include/gpu/GrProgramElement.h +++ b/include/gpu/GrProgramElement.h @@ -25,7 +25,7 @@ class GrGpuResourceRef; */ class GrProgramElement : public SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(GrProgramElement) + SK_DECLARE_INST_COUNT(GrProgramElement) virtual ~GrProgramElement() { // fRefCnt can be one when an effect is created statically using GR_CREATE_STATIC_EFFECT diff --git a/include/gpu/GrTextureAccess.h b/include/gpu/GrTextureAccess.h index 5055e103f5..db6f752bec 100644 --- a/include/gpu/GrTextureAccess.h +++ b/include/gpu/GrTextureAccess.h @@ -113,7 +113,7 @@ private: */ class GrTextureAccess : public SkNoncopyable { public: - SK_DECLARE_INST_COUNT_ROOT(GrTextureAccess); + SK_DECLARE_INST_COUNT(GrTextureAccess); /** * A default GrTextureAccess must have reset() called on it in a GrProcessor subclass's |