Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(365)

Side by Side Diff: include/core/SkInstCnt.h

Issue 841263004: Simplify SkInstCnt (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: T:: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | include/core/SkPath.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
9 #ifndef SkInstCnt_DEFINED 8 #ifndef SkInstCnt_DEFINED
10 #define SkInstCnt_DEFINED 9 #define SkInstCnt_DEFINED
11 10
12 /* 11 /* To count all instances of T, including all subclasses of T,
13 * The instance counting system consists of three macros that create the 12 * add SK_DECLARE_INST_COUNT(T) to T's class definition.
14 * instance counting machinery. A class is added to the system by adding: 13 * If you want to print out counts of leaked instances, set gPrintInstCount to t rue in main().
15 * SK_DECLARE_INST_COUNT at the top of its declaration for derived classes 14 *
16 * SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class 15 * E.g.
17 * At the end of an application a call to all the "root" objects' 16 * struct Base { SK_DECLARE_INST_COUNT(Base) };
18 * CheckInstanceCount methods should be made 17 * struct A : public Base {};
18 * struct SubBase : public Base { SK_DECLARE_INST_COUNT(SubBase); }
19 * struct B : public SubBase {};
20 *
21 * If gPrintInstCount is true, at the program exit you will see something like:
22 * Base: <N> leaked instances
23 * SubBase: <M> leaked instances
24 * where N >= M. Leaked instances of A count against Base; leaked instances of B count against
25 * both SubBase and Base.
26 *
27 * If SK_ENABLE_INST_COUNT is not defined or defined to 0, or we're in a shared library build,
28 * this entire system is compiled away to a noop.
19 */ 29 */
30
20 #include "SkTypes.h" 31 #include "SkTypes.h"
21 32
22 #if SK_ENABLE_INST_COUNT 33 #if SK_ENABLE_INST_COUNT && !defined(SKIA_DLL) // See skia:2058 for why we noop on shared builds.
23 // Static variables inside member functions below may be defined multiple times 34 #include "SkThread.h"
24 // if Skia is being used as a dynamic library. Instance counting should be on 35 #include <stdlib.h>
25 // only for static builds. See bug skia:2058. 36
26 #if defined(SKIA_DLL) 37 #define SK_DECLARE_INST_COUNT(T) \
27 #error Instance counting works only when Skia is built as a static library. 38 static const char* InstCountClassName() { return #T; } \
39 SkInstCount<T, T::InstCountClassName> fInstCnt; \
40 static int32_t GetInstanceCount() { return SkInstCount<T, InstCountClass Name>::Count(); }
41
42 extern bool gPrintInstCount;
43
44 template <typename T, const char*(Name)()>
45 class SkInstCount {
46 public:
47 SkInstCount() { Inc(); }
48 SkInstCount(const SkInstCount&) { Inc(); }
49 ~SkInstCount() { sk_atomic_dec(&gCount); }
50
51 SkInstCount& operator==(const SkInstCount&) { return *this; } // == can' t change the count.
52
53 static void Inc() {
54 // If it's the first time we go from 0 to 1, register to print leaks at process exit.
55 if (0 == sk_atomic_inc(&gCount) && sk_atomic_cas(&gRegistered, 0, 1) ) {
56 atexit(PrintAtExit);
57 }
58 }
59
60 static void PrintAtExit() {
61 int32_t leaks = Count();
62 if (gPrintInstCount && leaks > 0) {
63 SkDebugf("Leaked %s: %d\n", Name(), leaks);
64 }
65 }
66
67 // FIXME: Used publicly by unit tests. Seems like a bad idea in a DM wo rld.
68 static int32_t Count() { return sk_acquire_load(&gCount); }
69
70 private:
71 static int32_t gCount, gRegistered;
72 };
73 // As template values, these will be deduplicated. (No one-definition rule problems.)
74 template <typename T, const char*(Name)()> int32_t SkInstCount<T, Name>::gCo unt = 0;
75 template <typename T, const char*(Name)()> int32_t SkInstCount<T, Name>::gRe gistered = 0;
76 #else
77 #define SK_DECLARE_INST_COUNT(T)
28 #endif 78 #endif
29 79
30 #include "SkOnce.h"
31 #include "SkTArray.h"
32 #include "SkThread.h"
33 extern bool gPrintInstCount;
34
35 // The non-root classes just register themselves with their parent
36 #define SK_DECLARE_INST_COUNT(className) \
37 SK_DECLARE_INST_COUNT_INTERNAL(className, \
38 INHERITED::AddInstChild(CheckInstanceCount);)
39
40 // The root classes registers a function to print out the memory stats when
41 // the app ends
42 #define SK_DECLARE_INST_COUNT_ROOT(className) \
43 SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);)
44
45 #define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \
46 class SkInstanceCountHelper { \
47 public: \
48 SkInstanceCountHelper() { \
49 SK_DECLARE_STATIC_ONCE(once); \
50 SkOnce(&once, init); \
51 sk_atomic_inc(GetInstanceCountPtr()); \
52 } \
53 \
54 static void init() { \
55 initStep \
56 } \
57 \
58 SkInstanceCountHelper(const SkInstanceCountHelper&) { \
59 sk_atomic_inc(GetInstanceCountPtr()); \
60 } \
61 \
62 ~SkInstanceCountHelper() { \
63 sk_atomic_dec(GetInstanceCountPtr()); \
64 } \
65 \
66 static int32_t* GetInstanceCountPtr() { \
67 static int32_t gInstanceCount; \
68 return &gInstanceCount; \
69 } \
70 \
71 static SkTArray<int (*)(int, bool)>*& GetChildren() { \
72 static SkTArray<int (*)(int, bool)>* gChildren; \
73 return gChildren; \
74 } \
75 \
76 static void create_mutex(SkMutex** mutex) { \
77 *mutex = SkNEW(SkMutex); \
78 } \
79 static SkBaseMutex& GetChildrenMutex() { \
80 static SkMutex* childrenMutex; \
81 SK_DECLARE_STATIC_ONCE(once); \
82 SkOnce(&once, className::SkInstanceCountHelper::create_mutex, &child renMutex);\
83 return *childrenMutex; \
84 } \
85 \
86 } fInstanceCountHelper; \
87 \
88 static int32_t GetInstanceCount() { \
89 return *SkInstanceCountHelper::GetInstanceCountPtr(); \
90 } \
91 \
92 static void exitPrint() { \
93 CheckInstanceCount(0, true); \
94 } \
95 \
96 static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \
97 if (gPrintInstCount && 0 != GetInstanceCount()) { \
98 SkDebugf("%*c Leaked %s: %d\n", \
99 4*level, ' ', #className, \
100 GetInstanceCount()); \
101 } \
102 if (NULL == SkInstanceCountHelper::GetChildren()) { \
103 return GetInstanceCount(); \
104 } \
105 SkTArray<int (*)(int, bool)>* children = \
106 SkInstanceCountHelper::GetChildren(); \
107 int childCount = children->count(); \
108 int count = GetInstanceCount(); \
109 for (int i = 0; i < childCount; ++i) { \
110 count -= (*(*children)[i])(level+1, cleanUp); \
111 } \
112 SkASSERT(count >= 0); \
113 if (gPrintInstCount && childCount > 0 && count > 0) { \
114 SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \
115 } \
116 if (cleanUp) { \
117 delete children; \
118 SkInstanceCountHelper::GetChildren() = NULL; \
119 } \
120 return GetInstanceCount(); \
121 } \
122 \
123 static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \
124 if (CheckInstanceCount != childCheckInstCnt) { \
125 SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \
126 if (NULL == SkInstanceCountHelper::GetChildren()) { \
127 SkInstanceCountHelper::GetChildren() = \
128 new SkTArray<int (*)(int, bool)>; \
129 } \
130 SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \
131 } \
132 }
133
134 #else
135 // Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by
136 // causing a compile-time error if the typedef is missing. This way SK_ENABLE_IN ST_COUNT=1 stays
137 // compiling.
138 #define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED: :AddInstChild(); }
139 #define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { }
140 #endif
141
142 // Following are deprecated. They are defined only for backwards API compatibili ty.
143 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(classNam e)
144 #define SK_DEFINE_INST_COUNT(className)
145 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
146
147 #endif // SkInstCnt_DEFINED 80 #endif // SkInstCnt_DEFINED
OLDNEW
« no previous file with comments | « no previous file | include/core/SkPath.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698