blob: 7ed866befce11cfb3a074921173500965b2e3855 [file] [log] [blame]
robertphillips@google.comf6747b02012-06-12 00:32:28 +00001/*
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.
robertphillips@google.com977b9c82012-06-05 19:35:09 +00006 */
7
8
9#ifndef SkInstCnt_DEFINED
10#define SkInstCnt_DEFINED
11
12/*
rmistry@google.comfbfcd562012-08-23 18:09:54 +000013 * The instance counting system consists of three macros that create the
robertphillips@google.com977b9c82012-06-05 19:35:09 +000014 * instance counting machinery. A class is added to the system by adding:
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000015 * 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
robertphillips@google.com977b9c82012-06-05 19:35:09 +000020 */
robertphillips@google.comb74af872012-06-27 19:41:42 +000021#ifdef SK_ENABLE_INST_COUNT
robertphillips@google.com97fafe12012-06-27 19:52:20 +000022#include <stdlib.h>
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000023#include "SkTArray.h"
24
robertphillips@google.comb74af872012-06-27 19:41:42 +000025extern bool gPrintInstCount;
26
robertphillips@google.com97fafe12012-06-27 19:52:20 +000027// The non-root classes just register themselves with their parent
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000028#define SK_DECLARE_INST_COUNT(className) \
29 SK_DECLARE_INST_COUNT_INTERNAL(className, \
robertphillips@google.coma22e2112012-08-16 14:58:06 +000030 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)
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000037
robertphillips@google.com97fafe12012-06-27 19:52:20 +000038// The root classes registers a function to print out the memory stats when
39// the app ends
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000040#define SK_DECLARE_INST_COUNT_ROOT(className) \
robertphillips@google.coma22e2112012-08-16 14:58:06 +000041 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/)
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000042
robertphillips@google.coma22e2112012-08-16 14:58:06 +000043#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType) \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000044 class SkInstanceCountHelper { \
45 public: \
robertphillips@google.com23579272012-06-28 21:30:45 +000046 typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000047 SkInstanceCountHelper() { \
48 if (!gInited) { \
49 initStep \
robertphillips@google.com23579272012-06-28 21:30:45 +000050 gChildren = new SkTArray<PFCheckInstCnt>; \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000051 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; \
robertphillips@google.com23579272012-06-28 21:30:45 +000066 static SkTArray<PFCheckInstCnt>* gChildren; \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000067 } fInstanceCountHelper; \
68 \
bsalomon@google.com4da34e32012-06-19 15:40:27 +000069 static int32_t GetInstanceCount() { \
70 return SkInstanceCountHelper::gInstanceCount; \
71 } \
72 \
robertphillips@google.com97fafe12012-06-27 19:52:20 +000073 static void exitPrint() { \
robertphillips@google.com23579272012-06-28 21:30:45 +000074 CheckInstanceCount(0, true); \
robertphillips@google.com97fafe12012-06-27 19:52:20 +000075 } \
76 \
robertphillips@google.com23579272012-06-28 21:30:45 +000077 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \
robertphillips@google.comb74af872012-06-27 19:41:42 +000078 if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
reed@google.com73e19fb2012-06-26 18:58:03 +000079 SkDebugf("%*c Leaked %s: %d\n", \
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000080 4*level, ' ', #className, \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000081 SkInstanceCountHelper::gInstanceCount); \
82 } \
robertphillips@google.com23579272012-06-28 21:30:45 +000083 if (NULL == SkInstanceCountHelper::gChildren) { \
84 return SkInstanceCountHelper::gInstanceCount; \
85 } \
86 int childCount = SkInstanceCountHelper::gChildren->count(); \
reed@google.com73e19fb2012-06-26 18:58:03 +000087 int count = SkInstanceCountHelper::gInstanceCount; \
88 for (int i = 0; i < childCount; ++i) { \
robertphillips@google.com23579272012-06-28 21:30:45 +000089 count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000090 } \
reed@google.com73e19fb2012-06-26 18:58:03 +000091 SkASSERT(count >= 0); \
robertphillips@google.comb74af872012-06-27 19:41:42 +000092 if (gPrintInstCount && childCount > 0 && count > 0) { \
reed@google.com73e19fb2012-06-26 18:58:03 +000093 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \
94 } \
robertphillips@google.com23579272012-06-28 21:30:45 +000095 if (cleanUp) { \
96 delete SkInstanceCountHelper::gChildren; \
97 SkInstanceCountHelper::gChildren = NULL; \
98 } \
reed@google.com73e19fb2012-06-26 18:58:03 +000099 return SkInstanceCountHelper::gInstanceCount; \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000100 } \
101 \
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000102 static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000103 childCheckInstCnt) { \
robertphillips@google.com23579272012-06-28 21:30:45 +0000104 if (CheckInstanceCount != childCheckInstCnt && \
105 NULL != SkInstanceCountHelper::gChildren) { \
106 SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000107 } \
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000108 }
109
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000110#define SK_DEFINE_INST_COUNT(className) \
111 int32_t className::SkInstanceCountHelper::gInstanceCount = 0; \
112 bool className::SkInstanceCountHelper::gInited = false; \
robertphillips@google.com23579272012-06-28 21:30:45 +0000113 SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>* \
114 className::SkInstanceCountHelper::gChildren = NULL;
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000115
robertphillips@google.com4fa9c9f2012-08-22 17:31:22 +0000116#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) \
117 templateInfo int32_t className::SkInstanceCountHelper::gInstanceCount = 0;\
118 templateInfo bool className::SkInstanceCountHelper::gInited = false; \
119 templateInfo \
120 SkTArray<typename className::SkInstanceCountHelper::PFCheckInstCnt>*\
121 className::SkInstanceCountHelper::gChildren = NULL;
122
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000123#else
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000124#define SK_DECLARE_INST_COUNT(className)
robertphillips@google.coma22e2112012-08-16 14:58:06 +0000125#define SK_DECLARE_INST_COUNT_TEMPLATE(className)
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000126#define SK_DECLARE_INST_COUNT_ROOT(className)
127#define SK_DEFINE_INST_COUNT(className)
robertphillips@google.com4fa9c9f2012-08-22 17:31:22 +0000128#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000129#endif
130
131#endif // SkInstCnt_DEFINED