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 "SkTArray.h" 24 #include "SkThread_platform.h" 25 26 extern bool gPrintInstCount; 27 28 // The non-root classes just register themselves with their parent 29 #define SK_DECLARE_INST_COUNT(className) \ 30 SK_DECLARE_INST_COUNT_INTERNAL(className, \ 31 INHERITED::AddInstChild(CheckInstanceCount);) 32 33 // The root classes registers a function to print out the memory stats when 34 // the app ends 35 #define SK_DECLARE_INST_COUNT_ROOT(className) \ 36 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) 37 38 #define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ 39 class SkInstanceCountHelper { \ 40 public: \ 41 typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \ 42 SkInstanceCountHelper() { \ 43 static bool gInited; \ 44 if (!gInited) { \ 45 initStep \ 46 GetChildren() = new SkTArray<PFCheckInstCnt>; \ 47 gInited = true; \ 48 } \ 49 sk_atomic_inc(GetInstanceCountPtr()); \ 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<PFCheckInstCnt>*& GetChildren() { \ 66 static SkTArray<PFCheckInstCnt>* gChildren; \ 67 return gChildren; \ 68 } \ 69 \ 70 } fInstanceCountHelper; \ 71 \ 72 static int32_t GetInstanceCount() { \ 73 return *SkInstanceCountHelper::GetInstanceCountPtr(); \ 74 } \ 75 \ 76 static void exitPrint() { \ 77 CheckInstanceCount(0, true); \ 78 } \ 79 \ 80 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ 81 if (gPrintInstCount && 0 != GetInstanceCount()) { \ 82 SkDebugf("%*c Leaked %s: %d\n", \ 83 4*level, ' ', #className, \ 84 GetInstanceCount()); \ 85 } \ 86 if (NULL == SkInstanceCountHelper::GetChildren()) { \ 87 return GetInstanceCount(); \ 88 } \ 89 SkTArray<int (*)(int, bool)>* children = \ 90 SkInstanceCountHelper::GetChildren(); \ 91 int childCount = children->count(); \ 92 int count = GetInstanceCount(); \ 93 for (int i = 0; i < childCount; ++i) { \ 94 count -= (*(*children)[i])(level+1, cleanUp); \ 95 } \ 96 SkASSERT(count >= 0); \ 97 if (gPrintInstCount && childCount > 0 && count > 0) { \ 98 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ 99 } \ 100 if (cleanUp) { \ 101 delete children; \ 102 SkInstanceCountHelper::GetChildren() = NULL; \ 103 } \ 104 return GetInstanceCount(); \ 105 } \ 106 \ 107 static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ 108 if (CheckInstanceCount != childCheckInstCnt && \ 109 NULL != SkInstanceCountHelper::GetChildren()) { \ 110 SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \ 111 } \ 112 } 113 114 #else 115 // Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by 116 // causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays 117 // compiling. 118 #define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); } 119 #define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } 120 #endif 121 122 // Following are deprecated. They are defined only for backwards API compatibility. 123 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className) 124 #define SK_DEFINE_INST_COUNT(className) 125 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) 126 127 #endif // SkInstCnt_DEFINED 128