SkInstCnt.h revision 97fafe1b5ec06b470d36ea5cd98fe7bf2c143491
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);                           \
41        SkInstanceCountHelper() {                                           \
42            if (!gInited) {                                                 \
43                initStep                                                    \
44                gInited = true;                                             \
45            }                                                               \
46            gInstanceCount++;                                               \
47        }                                                                   \
48                                                                            \
49        SkInstanceCountHelper(const SkInstanceCountHelper& other) {         \
50            gInstanceCount++;                                               \
51        }                                                                   \
52                                                                            \
53        ~SkInstanceCountHelper() {                                          \
54            gInstanceCount--;                                               \
55        }                                                                   \
56                                                                            \
57        static int32_t gInstanceCount;                                      \
58        static bool gInited;                                                \
59        static SkTArray<PFCheckInstCnt> gChildren;                          \
60    } fInstanceCountHelper;                                                 \
61                                                                            \
62    static int32_t GetInstanceCount() {                                     \
63        return SkInstanceCountHelper::gInstanceCount;                       \
64    }                                                                       \
65                                                                            \
66    static void exitPrint() {                                               \
67        CheckInstanceCount();                                               \
68    }                                                                       \
69                                                                            \
70    static int CheckInstanceCount(int level = 0) {                          \
71        if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
72            SkDebugf("%*c Leaked %s: %d\n",                                 \
73                     4*level, ' ', #className,                              \
74                     SkInstanceCountHelper::gInstanceCount);                \
75        }                                                                   \
76        int childCount = SkInstanceCountHelper::gChildren.count();          \
77        int count = SkInstanceCountHelper::gInstanceCount;                  \
78        for (int i = 0; i < childCount; ++i) {                              \
79            count -= (*SkInstanceCountHelper::gChildren[i])(level+1);       \
80        }                                                                   \
81        SkASSERT(count >= 0);                                               \
82        if (gPrintInstCount && childCount > 0 && count > 0) {               \
83            SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
84        }                                                                   \
85        return SkInstanceCountHelper::gInstanceCount;                       \
86    }                                                                       \
87                                                                            \
88    static void AddInstChild(SkInstanceCountHelper::PFCheckInstCnt          \
89                                                       childCheckInstCnt) { \
90        if (CheckInstanceCount != childCheckInstCnt) {                      \
91            SkInstanceCountHelper::gChildren.push_back(childCheckInstCnt);  \
92        }                                                                   \
93    }
94
95#define SK_DEFINE_INST_COUNT(className)                                     \
96    int32_t className::SkInstanceCountHelper::gInstanceCount = 0;           \
97    bool className::SkInstanceCountHelper::gInited = false;                 \
98    SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>              \
99                        className::SkInstanceCountHelper::gChildren;
100
101#else
102#define SK_DECLARE_INST_COUNT(className)
103#define SK_DECLARE_INST_COUNT_ROOT(className)
104#define SK_DEFINE_INST_COUNT(className)
105#endif
106
107#endif // SkInstCnt_DEFINED
108