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