SkInstCnt.h revision 73e19fb1ba2562048c6987272c8d73eee6a44242
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 *   SK_DEFINE_INST_COUNT at the top of its .cpp file (for both kinds).
18 * At the end of an application a call to all the "root" objects'
19 * CheckInstanceCount methods should be made
20 */
21#ifdef SK_DEBUG
22#include "SkTArray.h"
23
24#define SK_DECLARE_INST_COUNT(className)                                    \
25    SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
26                                INHERITED::AddInstChild(CheckInstanceCount);)
27
28#define SK_DECLARE_INST_COUNT_ROOT(className)                               \
29    SK_DECLARE_INST_COUNT_INTERNAL(className, ;)
30
31#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep)                 \
32    class SkInstanceCountHelper {                                           \
33    public:                                                                 \
34        typedef int (*PFCheckInstCnt)(int level);                           \
35        SkInstanceCountHelper() {                                           \
36            if (!gInited) {                                                 \
37                initStep                                                    \
38                gInited = true;                                             \
39            }                                                               \
40            gInstanceCount++;                                               \
41        }                                                                   \
42                                                                            \
43        SkInstanceCountHelper(const SkInstanceCountHelper& other) {         \
44            gInstanceCount++;                                               \
45        }                                                                   \
46                                                                            \
47        ~SkInstanceCountHelper() {                                          \
48            gInstanceCount--;                                               \
49        }                                                                   \
50                                                                            \
51        static int32_t gInstanceCount;                                      \
52        static bool gInited;                                                \
53        static SkTArray<PFCheckInstCnt> gChildren;                          \
54    } fInstanceCountHelper;                                                 \
55                                                                            \
56    static int32_t GetInstanceCount() {                                     \
57        return SkInstanceCountHelper::gInstanceCount;                       \
58    }                                                                       \
59                                                                            \
60    static int CheckInstanceCount(int level = 0) {                          \
61        if (0 != SkInstanceCountHelper::gInstanceCount) {                   \
62            SkDebugf("%*c Leaked %s: %d\n",                                 \
63                     4*level, ' ', #className,                              \
64                     SkInstanceCountHelper::gInstanceCount);                \
65        }                                                                   \
66        int childCount = SkInstanceCountHelper::gChildren.count();          \
67        int count = SkInstanceCountHelper::gInstanceCount;                  \
68        for (int i = 0; i < childCount; ++i) {                              \
69            count -= (*SkInstanceCountHelper::gChildren[i])(level+1);       \
70        }                                                                   \
71        SkASSERT(count >= 0);                                               \
72        if (childCount > 0 && count > 0) {                                  \
73            SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
74        }                                                                   \
75        return SkInstanceCountHelper::gInstanceCount;                       \
76    }                                                                       \
77                                                                            \
78    static void AddInstChild(SkInstanceCountHelper::PFCheckInstCnt          \
79                                                       childCheckInstCnt) { \
80        if (CheckInstanceCount != childCheckInstCnt) {                      \
81            SkInstanceCountHelper::gChildren.push_back(childCheckInstCnt);  \
82        }                                                                   \
83    }
84
85#define SK_DEFINE_INST_COUNT(className)                                     \
86    int32_t className::SkInstanceCountHelper::gInstanceCount = 0;           \
87    bool className::SkInstanceCountHelper::gInited = false;                 \
88    SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>              \
89                        className::SkInstanceCountHelper::gChildren;
90
91#else
92#define SK_DECLARE_INST_COUNT(className)
93#define SK_DECLARE_INST_COUNT_ROOT(className)
94#define SK_DEFINE_INST_COUNT(className)
95#endif
96
97#endif // SkInstCnt_DEFINED
98