SkInstCnt.h revision 23579275c7f544763d074d90563c4b1e567ab041
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 <stdlib.h>
23#include "SkTArray.h"
24
25extern bool gPrintInstCount;
26
27// The non-root classes just register themselves with their parent
28#define SK_DECLARE_INST_COUNT(className)                                    \
29    SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
30                                INHERITED::AddInstChild(CheckInstanceCount);)
31
32// The root classes registers a function to print out the memory stats when
33// the app ends
34#define SK_DECLARE_INST_COUNT_ROOT(className)                               \
35    SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);)
36
37#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep)                 \
38    class SkInstanceCountHelper {                                           \
39    public:                                                                 \
40        typedef int (*PFCheckInstCnt)(int level, bool cleanUp);             \
41        SkInstanceCountHelper() {                                           \
42            if (!gInited) {                                                 \
43                initStep                                                    \
44                gChildren = new SkTArray<PFCheckInstCnt>;                   \
45                gInited = true;                                             \
46            }                                                               \
47            gInstanceCount++;                                               \
48        }                                                                   \
49                                                                            \
50        SkInstanceCountHelper(const SkInstanceCountHelper& other) {         \
51            gInstanceCount++;                                               \
52        }                                                                   \
53                                                                            \
54        ~SkInstanceCountHelper() {                                          \
55            gInstanceCount--;                                               \
56        }                                                                   \
57                                                                            \
58        static int32_t gInstanceCount;                                      \
59        static bool gInited;                                                \
60        static SkTArray<PFCheckInstCnt>* gChildren;                         \
61    } fInstanceCountHelper;                                                 \
62                                                                            \
63    static int32_t GetInstanceCount() {                                     \
64        return SkInstanceCountHelper::gInstanceCount;                       \
65    }                                                                       \
66                                                                            \
67    static void exitPrint() {                                               \
68        CheckInstanceCount(0, true);                                        \
69    }                                                                       \
70                                                                            \
71    static int CheckInstanceCount(int level = 0, bool cleanUp = false) {    \
72        if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
73            SkDebugf("%*c Leaked %s: %d\n",                                 \
74                     4*level, ' ', #className,                              \
75                     SkInstanceCountHelper::gInstanceCount);                \
76        }                                                                   \
77        if (NULL == SkInstanceCountHelper::gChildren) {                     \
78            return SkInstanceCountHelper::gInstanceCount;                   \
79        }                                                                   \
80        int childCount = SkInstanceCountHelper::gChildren->count();         \
81        int count = SkInstanceCountHelper::gInstanceCount;                  \
82        for (int i = 0; i < childCount; ++i) {                              \
83            count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \
84        }                                                                   \
85        SkASSERT(count >= 0);                                               \
86        if (gPrintInstCount && childCount > 0 && count > 0) {               \
87            SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
88        }                                                                   \
89        if (cleanUp) {                                                      \
90            delete SkInstanceCountHelper::gChildren;                        \
91            SkInstanceCountHelper::gChildren = NULL;                        \
92        }                                                                   \
93        return SkInstanceCountHelper::gInstanceCount;                       \
94    }                                                                       \
95                                                                            \
96    static void AddInstChild(SkInstanceCountHelper::PFCheckInstCnt          \
97                                                       childCheckInstCnt) { \
98        if (CheckInstanceCount != childCheckInstCnt &&                      \
99            NULL != SkInstanceCountHelper::gChildren) {                     \
100            SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \
101        }                                                                   \
102    }
103
104#define SK_DEFINE_INST_COUNT(className)                                     \
105    int32_t className::SkInstanceCountHelper::gInstanceCount = 0;           \
106    bool className::SkInstanceCountHelper::gInited = false;                 \
107    SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>*             \
108                        className::SkInstanceCountHelper::gChildren = NULL;
109
110#else
111#define SK_DECLARE_INST_COUNT(className)
112#define SK_DECLARE_INST_COUNT_ROOT(className)
113#define SK_DEFINE_INST_COUNT(className)
114#endif
115
116#endif // SkInstCnt_DEFINED
117