blob: e38c42d917a41bc3bc0dcec1e9cf218f525f7828 [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
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000017 * At the end of an application a call to all the "root" objects'
18 * CheckInstanceCount methods should be made
robertphillips@google.com977b9c82012-06-05 19:35:09 +000019 */
bsalomon@google.com4e230682013-01-15 20:37:04 +000020#include "SkTypes.h"
caryclark@google.com594dd3c2012-09-24 19:33:57 +000021
bsalomon@google.com4e230682013-01-15 20:37:04 +000022#if SK_ENABLE_INST_COUNT
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000023#include "SkTArray.h"
djsollen@google.comc9ab9872012-08-29 18:52:07 +000024#include "SkThread_platform.h"
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000025
robertphillips@google.comb74af872012-06-27 19:41:42 +000026extern bool gPrintInstCount;
27
robertphillips@google.com97fafe12012-06-27 19:52:20 +000028// The non-root classes just register themselves with their parent
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000029#define SK_DECLARE_INST_COUNT(className) \
30 SK_DECLARE_INST_COUNT_INTERNAL(className, \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000031 INHERITED::AddInstChild(CheckInstanceCount);)
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000032
robertphillips@google.com97fafe12012-06-27 19:52:20 +000033// The root classes registers a function to print out the memory stats when
34// the app ends
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000035#define SK_DECLARE_INST_COUNT_ROOT(className) \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000036 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);)
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000037
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000038#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000039 class SkInstanceCountHelper { \
40 public: \
robertphillips@google.com23579272012-06-28 21:30:45 +000041 typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000042 SkInstanceCountHelper() { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000043 static bool gInited; \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000044 if (!gInited) { \
45 initStep \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000046 GetChildren() = new SkTArray<PFCheckInstCnt>; \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000047 gInited = true; \
48 } \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000049 sk_atomic_inc(GetInstanceCountPtr()); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000050 } \
51 \
sugoi@google.come0e385c2013-03-11 18:50:03 +000052 SkInstanceCountHelper(const SkInstanceCountHelper&) { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000053 sk_atomic_inc(GetInstanceCountPtr()); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000054 } \
55 \
56 ~SkInstanceCountHelper() { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000057 sk_atomic_dec(GetInstanceCountPtr()); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000058 } \
59 \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000060 static int32_t* GetInstanceCountPtr() { \
61 static int32_t gInstanceCount; \
62 return &gInstanceCount; \
63 } \
64 \
65 static SkTArray<PFCheckInstCnt>*& GetChildren() { \
66 static SkTArray<PFCheckInstCnt>* gChildren; \
67 return gChildren; \
68 } \
69 \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000070 } fInstanceCountHelper; \
71 \
bsalomon@google.com4da34e32012-06-19 15:40:27 +000072 static int32_t GetInstanceCount() { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000073 return *SkInstanceCountHelper::GetInstanceCountPtr(); \
bsalomon@google.com4da34e32012-06-19 15:40:27 +000074 } \
75 \
robertphillips@google.com97fafe12012-06-27 19:52:20 +000076 static void exitPrint() { \
robertphillips@google.com23579272012-06-28 21:30:45 +000077 CheckInstanceCount(0, true); \
robertphillips@google.com97fafe12012-06-27 19:52:20 +000078 } \
79 \
robertphillips@google.com23579272012-06-28 21:30:45 +000080 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000081 if (gPrintInstCount && 0 != GetInstanceCount()) { \
reed@google.com73e19fb2012-06-26 18:58:03 +000082 SkDebugf("%*c Leaked %s: %d\n", \
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000083 4*level, ' ', #className, \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000084 GetInstanceCount()); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000085 } \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000086 if (NULL == SkInstanceCountHelper::GetChildren()) { \
87 return GetInstanceCount(); \
robertphillips@google.com23579272012-06-28 21:30:45 +000088 } \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000089 SkTArray<int (*)(int, bool)>* children = \
90 SkInstanceCountHelper::GetChildren(); \
91 int childCount = children->count(); \
92 int count = GetInstanceCount(); \
reed@google.com73e19fb2012-06-26 18:58:03 +000093 for (int i = 0; i < childCount; ++i) { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +000094 count -= (*(*children)[i])(level+1, cleanUp); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +000095 } \
reed@google.com73e19fb2012-06-26 18:58:03 +000096 SkASSERT(count >= 0); \
robertphillips@google.comb74af872012-06-27 19:41:42 +000097 if (gPrintInstCount && childCount > 0 && count > 0) { \
reed@google.com73e19fb2012-06-26 18:58:03 +000098 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \
99 } \
robertphillips@google.com23579272012-06-28 21:30:45 +0000100 if (cleanUp) { \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +0000101 delete children; \
102 SkInstanceCountHelper::GetChildren() = NULL; \
robertphillips@google.com23579272012-06-28 21:30:45 +0000103 } \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +0000104 return GetInstanceCount(); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000105 } \
106 \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +0000107 static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \
robertphillips@google.com23579272012-06-28 21:30:45 +0000108 if (CheckInstanceCount != childCheckInstCnt && \
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +0000109 NULL != SkInstanceCountHelper::GetChildren()) { \
110 SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000111 } \
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000112 }
113
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000114#else
commit-bot@chromium.orgab1c1382013-12-05 12:08:12 +0000115// Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by
116// causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays
117// compiling.
118#define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); }
119#define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { }
120#endif
121
122// Following are deprecated. They are defined only for backwards API compatibility.
123#define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className)
robertphillips@google.com4d73ac22012-06-13 18:54:08 +0000124#define SK_DEFINE_INST_COUNT(className)
robertphillips@google.com4fa9c9f2012-08-22 17:31:22 +0000125#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
robertphillips@google.com977b9c82012-06-05 19:35:09 +0000126
127#endif // SkInstCnt_DEFINED