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 * SK_DEFINE_INST_COUNT at the top of its .cpp file (for both kinds). 18 * At the end of an application a call to all the "root" objects' 19 * CheckInstanceCount methods should be made 20 */ 21 #include "SkTypes.h" 22 23 #if SK_ENABLE_INST_COUNT 24 #include "SkTArray.h" 25 #include "SkThread_platform.h" 26 27 extern 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 35 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) \ 36 SK_DECLARE_INST_COUNT_INTERNAL(className, \ 37 INHERITED::AddInstChild(CheckInstanceCount);, \ 38 typename) 39 40 // The root classes registers a function to print out the memory stats when 41 // the app ends 42 #define SK_DECLARE_INST_COUNT_ROOT(className) \ 43 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/) 44 45 #define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType) \ 46 class SkInstanceCountHelper { \ 47 public: \ 48 typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \ 49 SkInstanceCountHelper() { \ 50 if (!gInited) { \ 51 initStep \ 52 gChildren = new SkTArray<PFCheckInstCnt>; \ 53 gInited = true; \ 54 } \ 55 sk_atomic_inc(&gInstanceCount); \ 56 } \ 57 \ 58 SkInstanceCountHelper(const SkInstanceCountHelper& other) { \ 59 sk_atomic_inc(&gInstanceCount); \ 60 } \ 61 \ 62 ~SkInstanceCountHelper() { \ 63 sk_atomic_dec(&gInstanceCount); \ 64 } \ 65 \ 66 static int32_t gInstanceCount; \ 67 static bool gInited; \ 68 static SkTArray<PFCheckInstCnt>* gChildren; \ 69 } fInstanceCountHelper; \ 70 \ 71 static int32_t GetInstanceCount() { \ 72 return SkInstanceCountHelper::gInstanceCount; \ 73 } \ 74 \ 75 static void exitPrint() { \ 76 CheckInstanceCount(0, true); \ 77 } \ 78 \ 79 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ 80 if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\ 81 SkDebugf("%*c Leaked %s: %d\n", \ 82 4*level, ' ', #className, \ 83 SkInstanceCountHelper::gInstanceCount); \ 84 } \ 85 if (NULL == SkInstanceCountHelper::gChildren) { \ 86 return SkInstanceCountHelper::gInstanceCount; \ 87 } \ 88 int childCount = SkInstanceCountHelper::gChildren->count(); \ 89 int count = SkInstanceCountHelper::gInstanceCount; \ 90 for (int i = 0; i < childCount; ++i) { \ 91 count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \ 92 } \ 93 SkASSERT(count >= 0); \ 94 if (gPrintInstCount && childCount > 0 && count > 0) { \ 95 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ 96 } \ 97 if (cleanUp) { \ 98 delete SkInstanceCountHelper::gChildren; \ 99 SkInstanceCountHelper::gChildren = NULL; \ 100 } \ 101 return SkInstanceCountHelper::gInstanceCount; \ 102 } \ 103 \ 104 static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \ 105 childCheckInstCnt) { \ 106 if (CheckInstanceCount != childCheckInstCnt && \ 107 NULL != SkInstanceCountHelper::gChildren) { \ 108 SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \ 109 } \ 110 } 111 112 #define SK_DEFINE_INST_COUNT(className) \ 113 int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \ 114 bool className::SkInstanceCountHelper::gInited = false; \ 115 SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>* \ 116 className::SkInstanceCountHelper::gChildren = NULL; 117 118 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) \ 119 templateInfo int32_t className::SkInstanceCountHelper::gInstanceCount = 0;\ 120 templateInfo bool className::SkInstanceCountHelper::gInited = false; \ 121 templateInfo \ 122 SkTArray<typename className::SkInstanceCountHelper::PFCheckInstCnt>*\ 123 className::SkInstanceCountHelper::gChildren = NULL; 124 125 #else 126 #define SK_DECLARE_INST_COUNT(className) 127 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) 128 #define SK_DECLARE_INST_COUNT_ROOT(className) 129 #define SK_DEFINE_INST_COUNT(className) 130 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) 131 #endif 132 133 #endif // SkInstCnt_DEFINED 134