• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * At the end of an application a call to all the "root" objects'
18  * CheckInstanceCount methods should be made
19  */
20 #include "SkTypes.h"
21 
22 #if SK_ENABLE_INST_COUNT
23 #include "SkTArray.h"
24 #include "SkThread_platform.h"
25 
26 extern bool gPrintInstCount;
27 
28 // The non-root classes just register themselves with their parent
29 #define SK_DECLARE_INST_COUNT(className)                                    \
30     SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
31                                    INHERITED::AddInstChild(CheckInstanceCount);)
32 
33 // The root classes registers a function to print out the memory stats when
34 // the app ends
35 #define SK_DECLARE_INST_COUNT_ROOT(className)                               \
36     SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);)
37 
38 #define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep)                 \
39     class SkInstanceCountHelper {                                           \
40     public:                                                                 \
41         typedef int (*PFCheckInstCnt)(int level, bool cleanUp);             \
42         SkInstanceCountHelper() {                                           \
43             static bool gInited;                                            \
44             if (!gInited) {                                                 \
45                 initStep                                                    \
46                 GetChildren() = new SkTArray<PFCheckInstCnt>;               \
47                 gInited = true;                                             \
48             }                                                               \
49             sk_atomic_inc(GetInstanceCountPtr());                           \
50         }                                                                   \
51                                                                             \
52         SkInstanceCountHelper(const SkInstanceCountHelper&) {               \
53             sk_atomic_inc(GetInstanceCountPtr());                           \
54         }                                                                   \
55                                                                             \
56         ~SkInstanceCountHelper() {                                          \
57             sk_atomic_dec(GetInstanceCountPtr());                           \
58         }                                                                   \
59                                                                             \
60         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                                                                             \
70     } fInstanceCountHelper;                                                 \
71                                                                             \
72     static int32_t GetInstanceCount() {                                     \
73         return *SkInstanceCountHelper::GetInstanceCountPtr();               \
74     }                                                                       \
75                                                                             \
76     static void exitPrint() {                                               \
77         CheckInstanceCount(0, true);                                        \
78     }                                                                       \
79                                                                             \
80     static int CheckInstanceCount(int level = 0, bool cleanUp = false) {    \
81         if (gPrintInstCount && 0 != GetInstanceCount()) {                   \
82             SkDebugf("%*c Leaked %s: %d\n",                                 \
83                      4*level, ' ', #className,                              \
84                      GetInstanceCount());                                   \
85         }                                                                   \
86         if (NULL == SkInstanceCountHelper::GetChildren()) {                 \
87             return GetInstanceCount();                                      \
88         }                                                                   \
89         SkTArray<int (*)(int, bool)>* children =                            \
90             SkInstanceCountHelper::GetChildren();                           \
91         int childCount = children->count();                                 \
92         int count = GetInstanceCount();                                     \
93         for (int i = 0; i < childCount; ++i) {                              \
94             count -= (*(*children)[i])(level+1, cleanUp);                   \
95         }                                                                   \
96         SkASSERT(count >= 0);                                               \
97         if (gPrintInstCount && childCount > 0 && count > 0) {               \
98             SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
99         }                                                                   \
100         if (cleanUp) {                                                      \
101             delete children;                                                \
102             SkInstanceCountHelper::GetChildren() = NULL;                    \
103         }                                                                   \
104         return GetInstanceCount();                                          \
105     }                                                                       \
106                                                                             \
107     static void AddInstChild(int (*childCheckInstCnt)(int, bool)) {         \
108         if (CheckInstanceCount != childCheckInstCnt &&                      \
109             NULL != SkInstanceCountHelper::GetChildren()) {                 \
110             SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \
111         }                                                                   \
112     }
113 
114 #else
115 // 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)
124 #define SK_DEFINE_INST_COUNT(className)
125 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
126 
127 #endif // SkInstCnt_DEFINED
128