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