SkInstCnt.h revision 46de153d4e887d82b5309316ed2e26e5cdc291f0
1/* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 9#ifndef SkInstCnt_DEFINED 10#define SkInstCnt_DEFINED 11 12/* 13 * The instance counting system consists of three macros that create the 14 * instance counting machinery. A class is added to the system by adding: 15 * SK_DECLARE_INST_COUNT at the top of its declaration for derived classes 16 * SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class 17 * At the end of an application a call to all the "root" objects' 18 * CheckInstanceCount methods should be made 19 */ 20#include "SkTypes.h" 21 22#if SK_ENABLE_INST_COUNT 23#include "SkOnce.h" 24#include "SkTArray.h" 25#include "SkThread.h" 26 27extern bool gPrintInstCount; 28 29// The non-root classes just register themselves with their parent 30#define SK_DECLARE_INST_COUNT(className) \ 31 SK_DECLARE_INST_COUNT_INTERNAL(className, \ 32 INHERITED::AddInstChild(CheckInstanceCount);) 33 34// The root classes registers a function to print out the memory stats when 35// the app ends 36#define SK_DECLARE_INST_COUNT_ROOT(className) \ 37 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) 38 39#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ 40 class SkInstanceCountHelper { \ 41 public: \ 42 SkInstanceCountHelper() { \ 43 SK_DECLARE_STATIC_ONCE(once); \ 44 SkOnce(&once, init, 0); \ 45 sk_atomic_inc(GetInstanceCountPtr()); \ 46 } \ 47 \ 48 static void init(int) { \ 49 initStep \ 50 } \ 51 \ 52 SkInstanceCountHelper(const SkInstanceCountHelper&) { \ 53 sk_atomic_inc(GetInstanceCountPtr()); \ 54 } \ 55 \ 56 ~SkInstanceCountHelper() { \ 57 sk_atomic_dec(GetInstanceCountPtr()); \ 58 } \ 59 \ 60 static int32_t* GetInstanceCountPtr() { \ 61 static int32_t gInstanceCount; \ 62 return &gInstanceCount; \ 63 } \ 64 \ 65 static SkTArray<int (*)(int, bool)>*& GetChildren() { \ 66 static SkTArray<int (*)(int, bool)>* gChildren; \ 67 return gChildren; \ 68 } \ 69 \ 70 static SkBaseMutex& GetChildrenMutex() { \ 71 SK_DECLARE_STATIC_MUTEX(childrenMutex); \ 72 return childrenMutex; \ 73 } \ 74 \ 75 } fInstanceCountHelper; \ 76 \ 77 static int32_t GetInstanceCount() { \ 78 return *SkInstanceCountHelper::GetInstanceCountPtr(); \ 79 } \ 80 \ 81 static void exitPrint() { \ 82 CheckInstanceCount(0, true); \ 83 } \ 84 \ 85 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ 86 if (gPrintInstCount && 0 != GetInstanceCount()) { \ 87 SkDebugf("%*c Leaked %s: %d\n", \ 88 4*level, ' ', #className, \ 89 GetInstanceCount()); \ 90 } \ 91 if (NULL == SkInstanceCountHelper::GetChildren()) { \ 92 return GetInstanceCount(); \ 93 } \ 94 SkTArray<int (*)(int, bool)>* children = \ 95 SkInstanceCountHelper::GetChildren(); \ 96 int childCount = children->count(); \ 97 int count = GetInstanceCount(); \ 98 for (int i = 0; i < childCount; ++i) { \ 99 count -= (*(*children)[i])(level+1, cleanUp); \ 100 } \ 101 SkASSERT(count >= 0); \ 102 if (gPrintInstCount && childCount > 0 && count > 0) { \ 103 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ 104 } \ 105 if (cleanUp) { \ 106 delete children; \ 107 SkInstanceCountHelper::GetChildren() = NULL; \ 108 } \ 109 return GetInstanceCount(); \ 110 } \ 111 \ 112 static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ 113 if (CheckInstanceCount != childCheckInstCnt) { \ 114 SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \ 115 if (NULL == SkInstanceCountHelper::GetChildren()) { \ 116 SkInstanceCountHelper::GetChildren() = \ 117 new SkTArray<int (*)(int, bool)>; \ 118 } \ 119 SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \ 120 } \ 121 } 122 123#else 124// Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by 125// causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays 126// compiling. 127#define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); } 128#define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } 129#endif 130 131// Following are deprecated. They are defined only for backwards API compatibility. 132#define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className) 133#define SK_DEFINE_INST_COUNT(className) 134#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) 135 136#endif // SkInstCnt_DEFINED 137