SkInstCnt.h revision 97fafe1b5ec06b470d36ea5cd98fe7bf2c143491
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); \ 41 SkInstanceCountHelper() { \ 42 if (!gInited) { \ 43 initStep \ 44 gInited = true; \ 45 } \ 46 gInstanceCount++; \ 47 } \ 48 \ 49 SkInstanceCountHelper(const SkInstanceCountHelper& other) { \ 50 gInstanceCount++; \ 51 } \ 52 \ 53 ~SkInstanceCountHelper() { \ 54 gInstanceCount--; \ 55 } \ 56 \ 57 static int32_t gInstanceCount; \ 58 static bool gInited; \ 59 static SkTArray<PFCheckInstCnt> gChildren; \ 60 } fInstanceCountHelper; \ 61 \ 62 static int32_t GetInstanceCount() { \ 63 return SkInstanceCountHelper::gInstanceCount; \ 64 } \ 65 \ 66 static void exitPrint() { \ 67 CheckInstanceCount(); \ 68 } \ 69 \ 70 static int CheckInstanceCount(int level = 0) { \ 71 if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\ 72 SkDebugf("%*c Leaked %s: %d\n", \ 73 4*level, ' ', #className, \ 74 SkInstanceCountHelper::gInstanceCount); \ 75 } \ 76 int childCount = SkInstanceCountHelper::gChildren.count(); \ 77 int count = SkInstanceCountHelper::gInstanceCount; \ 78 for (int i = 0; i < childCount; ++i) { \ 79 count -= (*SkInstanceCountHelper::gChildren[i])(level+1); \ 80 } \ 81 SkASSERT(count >= 0); \ 82 if (gPrintInstCount && childCount > 0 && count > 0) { \ 83 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ 84 } \ 85 return SkInstanceCountHelper::gInstanceCount; \ 86 } \ 87 \ 88 static void AddInstChild(SkInstanceCountHelper::PFCheckInstCnt \ 89 childCheckInstCnt) { \ 90 if (CheckInstanceCount != childCheckInstCnt) { \ 91 SkInstanceCountHelper::gChildren.push_back(childCheckInstCnt); \ 92 } \ 93 } 94 95#define SK_DEFINE_INST_COUNT(className) \ 96 int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \ 97 bool className::SkInstanceCountHelper::gInited = false; \ 98 SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt> \ 99 className::SkInstanceCountHelper::gChildren; 100 101#else 102#define SK_DECLARE_INST_COUNT(className) 103#define SK_DECLARE_INST_COUNT_ROOT(className) 104#define SK_DEFINE_INST_COUNT(className) 105#endif 106 107#endif // SkInstCnt_DEFINED 108