SkInstCnt.h revision a22e2117e44efa4298dd0eb6df304a8166c8e9c3
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#ifdef SK_ENABLE_INST_COUNT 22#include <stdlib.h> 23#include "SkTArray.h" 24 25extern bool gPrintInstCount; 26 27// The non-root classes just register themselves with their parent 28#define SK_DECLARE_INST_COUNT(className) \ 29 SK_DECLARE_INST_COUNT_INTERNAL(className, \ 30 INHERITED::AddInstChild(CheckInstanceCount);,\ 31 /**/) 32 33#define SK_DECLARE_INST_COUNT_TEMPLATE(className) \ 34 SK_DECLARE_INST_COUNT_INTERNAL(className, \ 35 INHERITED::AddInstChild(CheckInstanceCount);, \ 36 typename) 37 38// The root classes registers a function to print out the memory stats when 39// the app ends 40#define SK_DECLARE_INST_COUNT_ROOT(className) \ 41 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/) 42 43#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType) \ 44 class SkInstanceCountHelper { \ 45 public: \ 46 typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \ 47 SkInstanceCountHelper() { \ 48 if (!gInited) { \ 49 initStep \ 50 gChildren = new SkTArray<PFCheckInstCnt>; \ 51 gInited = true; \ 52 } \ 53 gInstanceCount++; \ 54 } \ 55 \ 56 SkInstanceCountHelper(const SkInstanceCountHelper& other) { \ 57 gInstanceCount++; \ 58 } \ 59 \ 60 ~SkInstanceCountHelper() { \ 61 gInstanceCount--; \ 62 } \ 63 \ 64 static int32_t gInstanceCount; \ 65 static bool gInited; \ 66 static SkTArray<PFCheckInstCnt>* gChildren; \ 67 } fInstanceCountHelper; \ 68 \ 69 static int32_t GetInstanceCount() { \ 70 return SkInstanceCountHelper::gInstanceCount; \ 71 } \ 72 \ 73 static void exitPrint() { \ 74 CheckInstanceCount(0, true); \ 75 } \ 76 \ 77 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ 78 if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\ 79 SkDebugf("%*c Leaked %s: %d\n", \ 80 4*level, ' ', #className, \ 81 SkInstanceCountHelper::gInstanceCount); \ 82 } \ 83 if (NULL == SkInstanceCountHelper::gChildren) { \ 84 return SkInstanceCountHelper::gInstanceCount; \ 85 } \ 86 int childCount = SkInstanceCountHelper::gChildren->count(); \ 87 int count = SkInstanceCountHelper::gInstanceCount; \ 88 for (int i = 0; i < childCount; ++i) { \ 89 count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \ 90 } \ 91 SkASSERT(count >= 0); \ 92 if (gPrintInstCount && childCount > 0 && count > 0) { \ 93 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ 94 } \ 95 if (cleanUp) { \ 96 delete SkInstanceCountHelper::gChildren; \ 97 SkInstanceCountHelper::gChildren = NULL; \ 98 } \ 99 return SkInstanceCountHelper::gInstanceCount; \ 100 } \ 101 \ 102 static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \ 103 childCheckInstCnt) { \ 104 if (CheckInstanceCount != childCheckInstCnt && \ 105 NULL != SkInstanceCountHelper::gChildren) { \ 106 SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \ 107 } \ 108 } 109 110#define SK_DEFINE_INST_COUNT(className) \ 111 int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \ 112 bool className::SkInstanceCountHelper::gInited = false; \ 113 SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>* \ 114 className::SkInstanceCountHelper::gChildren = NULL; 115 116#else 117#define SK_DECLARE_INST_COUNT(className) 118#define SK_DECLARE_INST_COUNT_TEMPLATE(className) 119#define SK_DECLARE_INST_COUNT_ROOT(className) 120#define SK_DEFINE_INST_COUNT(className) 121#endif 122 123#endif // SkInstCnt_DEFINED 124