OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 | 8 |
9 #ifndef SkInstCnt_DEFINED | 9 #ifndef SkInstCnt_DEFINED |
10 #define SkInstCnt_DEFINED | 10 #define SkInstCnt_DEFINED |
11 | 11 |
12 /* | 12 /* |
13 * The instance counting system consists of three macros that create the | 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: | 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 | 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 | 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' | 17 * At the end of an application a call to all the "root" objects' |
18 * CheckInstanceCount methods should be made | 18 * CheckInstanceCount methods should be made |
19 */ | 19 */ |
20 #include "SkTypes.h" | 20 #include "SkTypes.h" |
21 | 21 |
22 #if SK_ENABLE_INST_COUNT | 22 #if SK_ENABLE_INST_COUNT |
23 #include "SkOnce.h" | |
24 #include "SkTArray.h" | 23 #include "SkTArray.h" |
25 #include "SkThread.h" | 24 #include "SkThread.h" |
26 | 25 |
27 extern bool gPrintInstCount; | 26 extern bool gPrintInstCount; |
28 | 27 |
29 // The non-root classes just register themselves with their parent | 28 // The non-root classes just register themselves with their parent |
30 #define SK_DECLARE_INST_COUNT(className) \ | 29 #define SK_DECLARE_INST_COUNT(className) \ |
31 SK_DECLARE_INST_COUNT_INTERNAL(className, \ | 30 SK_DECLARE_INST_COUNT_INTERNAL(className, \ |
32 INHERITED::AddInstChild(CheckInstanceCount);) | 31 INHERITED::AddInstChild(CheckInstanceCount);) |
33 | 32 |
34 // The root classes registers a function to print out the memory stats when | 33 // The root classes registers a function to print out the memory stats when |
35 // the app ends | 34 // the app ends |
36 #define SK_DECLARE_INST_COUNT_ROOT(className) \ | 35 #define SK_DECLARE_INST_COUNT_ROOT(className) \ |
37 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) | 36 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) |
38 | 37 |
39 #define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ | 38 #define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ |
40 class SkInstanceCountHelper { \ | 39 class SkInstanceCountHelper { \ |
41 public: \ | 40 public: \ |
| 41 typedef int (*PFCheckInstCnt)(int level, bool cleanUp); \ |
42 SkInstanceCountHelper() { \ | 42 SkInstanceCountHelper() { \ |
43 SK_DECLARE_STATIC_ONCE(once); \ | 43 static bool gInited; \ |
44 SkOnce(&once, init, 0); \ | 44 if (!gInited) { \ |
| 45 initStep \ |
| 46 GetChildren() = new SkTArray<PFCheckInstCnt>; \ |
| 47 gInited = true; \ |
| 48 } \ |
45 sk_atomic_inc(GetInstanceCountPtr()); \ | 49 sk_atomic_inc(GetInstanceCountPtr()); \ |
46 } \ | 50 } \ |
47 \ | 51 \ |
48 static void init(int) { \ | |
49 initStep \ | |
50 } \ | |
51 \ | |
52 SkInstanceCountHelper(const SkInstanceCountHelper&) { \ | 52 SkInstanceCountHelper(const SkInstanceCountHelper&) { \ |
53 sk_atomic_inc(GetInstanceCountPtr()); \ | 53 sk_atomic_inc(GetInstanceCountPtr()); \ |
54 } \ | 54 } \ |
55 \ | 55 \ |
56 ~SkInstanceCountHelper() { \ | 56 ~SkInstanceCountHelper() { \ |
57 sk_atomic_dec(GetInstanceCountPtr()); \ | 57 sk_atomic_dec(GetInstanceCountPtr()); \ |
58 } \ | 58 } \ |
59 \ | 59 \ |
60 static int32_t* GetInstanceCountPtr() { \ | 60 static int32_t* GetInstanceCountPtr() { \ |
61 static int32_t gInstanceCount; \ | 61 static int32_t gInstanceCount; \ |
62 return &gInstanceCount; \ | 62 return &gInstanceCount; \ |
63 } \ | 63 } \ |
64 \ | 64 \ |
65 static SkTArray<int (*)(int, bool)>*& GetChildren() { \ | 65 static SkTArray<PFCheckInstCnt>*& GetChildren() { \ |
66 static SkTArray<int (*)(int, bool)>* gChildren; \ | 66 static SkTArray<PFCheckInstCnt>* gChildren; \ |
67 return gChildren; \ | 67 return gChildren; \ |
68 } \ | 68 } \ |
69 \ | 69 \ |
70 static SkBaseMutex& GetChildrenMutex() { \ | |
71 SK_DECLARE_STATIC_MUTEX(childrenMutex); \ | |
72 return childrenMutex; \ | |
73 } \ | |
74 \ | |
75 } fInstanceCountHelper; \ | 70 } fInstanceCountHelper; \ |
76 \ | 71 \ |
77 static int32_t GetInstanceCount() { \ | 72 static int32_t GetInstanceCount() { \ |
78 return *SkInstanceCountHelper::GetInstanceCountPtr(); \ | 73 return *SkInstanceCountHelper::GetInstanceCountPtr(); \ |
79 } \ | 74 } \ |
80 \ | 75 \ |
81 static void exitPrint() { \ | 76 static void exitPrint() { \ |
82 CheckInstanceCount(0, true); \ | 77 CheckInstanceCount(0, true); \ |
83 } \ | 78 } \ |
84 \ | 79 \ |
85 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ | 80 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ |
86 if (gPrintInstCount && 0 != GetInstanceCount()) { \ | 81 if (gPrintInstCount && 0 != GetInstanceCount()) { \ |
87 SkDebugf("%*c Leaked %s: %d\n", \ | 82 SkDebugf("%*c Leaked %s: %d\n", \ |
88 4*level, ' ', #className, \ | 83 4*level, ' ', #className, \ |
89 GetInstanceCount()); \ | 84 GetInstanceCount()); \ |
90 } \ | 85 } \ |
91 if (NULL == SkInstanceCountHelper::GetChildren()) { \ | 86 if (NULL == SkInstanceCountHelper::GetChildren()) { \ |
92 return GetInstanceCount(); \ | 87 return GetInstanceCount(); \ |
93 } \ | 88 } \ |
94 SkTArray<int (*)(int, bool)>* children = \ | 89 SkTArray<int (*)(int, bool)>* children = \ |
95 SkInstanceCountHelper::GetChildren(); \ | 90 SkInstanceCountHelper::GetChildren(); \ |
96 int childCount = children->count(); \ | 91 int childCount = children->count(); \ |
97 int count = GetInstanceCount(); \ | 92 int count = GetInstanceCount(); \ |
98 for (int i = 0; i < childCount; ++i) { \ | 93 for (int i = 0; i < childCount; ++i) { \ |
99 count -= (*(*children)[i])(level+1, cleanUp); \ | 94 count -= (*(*children)[i])(level+1, cleanUp); \ |
100 } \ | 95 } \ |
101 SkASSERT(count >= 0); \ | 96 SkASSERT(count >= 0); \ |
102 if (gPrintInstCount && childCount > 0 && count > 0) { \ | 97 if (gPrintInstCount && childCount > 0 && count > 0) { \ |
103 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ | 98 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ |
104 } \ | 99 } \ |
105 if (cleanUp) { \ | 100 if (cleanUp) { \ |
106 delete children; \ | 101 delete children; \ |
107 SkInstanceCountHelper::GetChildren() = NULL; \ | 102 SkInstanceCountHelper::GetChildren() = NULL; \ |
108 } \ | 103 } \ |
109 return GetInstanceCount(); \ | 104 return GetInstanceCount(); \ |
110 } \ | 105 } \ |
111 \ | 106 \ |
112 static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ | 107 static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ |
113 if (CheckInstanceCount != childCheckInstCnt) { \ | 108 if (CheckInstanceCount != childCheckInstCnt && \ |
114 SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \ | 109 NULL != SkInstanceCountHelper::GetChildren()) { \ |
115 if (NULL == SkInstanceCountHelper::GetChildren()) { \ | |
116 SkInstanceCountHelper::GetChildren() = \ | |
117 new SkTArray<int (*)(int, bool)>; \ | |
118 } \ | |
119 SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt);
\ | 110 SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt);
\ |
120 } \ | 111 } \ |
121 } | 112 } |
122 | 113 |
123 #else | 114 #else |
124 // Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef
INHERITED by | 115 // Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef
INHERITED by |
125 // causing a compile-time error if the typedef is missing. This way SK_ENABLE_IN
ST_COUNT=1 stays | 116 // causing a compile-time error if the typedef is missing. This way SK_ENABLE_IN
ST_COUNT=1 stays |
126 // compiling. | 117 // compiling. |
127 #define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED:
:AddInstChild(); } | 118 #define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED:
:AddInstChild(); } |
128 #define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } | 119 #define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } |
129 #endif | 120 #endif |
130 | 121 |
131 // Following are deprecated. They are defined only for backwards API compatibili
ty. | 122 // Following are deprecated. They are defined only for backwards API compatibili
ty. |
132 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(classNam
e) | 123 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(classNam
e) |
133 #define SK_DEFINE_INST_COUNT(className) | 124 #define SK_DEFINE_INST_COUNT(className) |
134 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) | 125 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) |
135 | 126 |
136 #endif // SkInstCnt_DEFINED | 127 #endif // SkInstCnt_DEFINED |
OLD | NEW |