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