Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / core / SkInstCnt.h
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 // Static variables inside member functions below may be defined multiple times
24 // if Skia is being used as a dynamic library. Instance counting should be on
25 // only for static builds. See bug skia:2058.
26 #if defined(SKIA_DLL)
27 #error Instance counting works only when Skia is built as a static library.
28 #endif
29
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, &childrenMutex);\
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_INST_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 compatibility.
143 #define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className)
144 #define SK_DEFINE_INST_COUNT(className)
145 #define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
146
147 #endif // SkInstCnt_DEFINED