SkInstCnt.h revision fbfcd5602128ec010c82cb733c9cdc0a3254f9f3
1f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com/*
2f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com * Copyright 2012 Google Inc.
3f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com *
4f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
5f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com * found in the LICENSE file.
6977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com */
7977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
8977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
9977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#ifndef SkInstCnt_DEFINED
10977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#define SkInstCnt_DEFINED
11977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
12977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com/*
13fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * The instance counting system consists of three macros that create the
14977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com * instance counting machinery. A class is added to the system by adding:
154d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com *   SK_DECLARE_INST_COUNT at the top of its declaration for derived classes
164d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com *   SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class
174d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com *   SK_DEFINE_INST_COUNT at the top of its .cpp file (for both kinds).
184d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com * At the end of an application a call to all the "root" objects'
194d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com * CheckInstanceCount methods should be made
20977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com */
21b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com#ifdef SK_ENABLE_INST_COUNT
2297fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com#include <stdlib.h>
234d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#include "SkTArray.h"
244d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
25b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.comextern bool gPrintInstCount;
26b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com
2797fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com// The non-root classes just register themselves with their parent
284d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT(className)                                    \
294d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
30a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com                               INHERITED::AddInstChild(CheckInstanceCount);,\
31a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com                               /**/)
32a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com
33a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com#define SK_DECLARE_INST_COUNT_TEMPLATE(className)                           \
34a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com    SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
35a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com                              INHERITED::AddInstChild(CheckInstanceCount);, \
36a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com                              typename)
374d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
3897fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com// The root classes registers a function to print out the memory stats when
3997fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com// the app ends
404d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT_ROOT(className)                               \
41a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com    SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);, /**/)
424d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
43a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep, templateType)   \
444d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    class SkInstanceCountHelper {                                           \
454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    public:                                                                 \
4623579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        typedef int (*PFCheckInstCnt)(int level, bool cleanUp);             \
474d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        SkInstanceCountHelper() {                                           \
484d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            if (!gInited) {                                                 \
494d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                initStep                                                    \
5023579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com                gChildren = new SkTArray<PFCheckInstCnt>;                   \
514d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                gInited = true;                                             \
524d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            }                                                               \
534d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            gInstanceCount++;                                               \
544d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
554d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
564d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        SkInstanceCountHelper(const SkInstanceCountHelper& other) {         \
574d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            gInstanceCount++;                                               \
584d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
594d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
604d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        ~SkInstanceCountHelper() {                                          \
614d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            gInstanceCount--;                                               \
624d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
634d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
644d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        static int32_t gInstanceCount;                                      \
654d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        static bool gInited;                                                \
6623579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        static SkTArray<PFCheckInstCnt>* gChildren;                         \
674d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    } fInstanceCountHelper;                                                 \
684d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
694da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    static int32_t GetInstanceCount() {                                     \
704da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        return SkInstanceCountHelper::gInstanceCount;                       \
714da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    }                                                                       \
724da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com                                                                            \
7397fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com    static void exitPrint() {                                               \
7423579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        CheckInstanceCount(0, true);                                        \
7597fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com    }                                                                       \
7697fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com                                                                            \
7723579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com    static int CheckInstanceCount(int level = 0, bool cleanUp = false) {    \
78b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com        if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
7973e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            SkDebugf("%*c Leaked %s: %d\n",                                 \
8015e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com                     4*level, ' ', #className,                              \
814d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                     SkInstanceCountHelper::gInstanceCount);                \
824d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
8323579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        if (NULL == SkInstanceCountHelper::gChildren) {                     \
8423579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com            return SkInstanceCountHelper::gInstanceCount;                   \
8523579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        }                                                                   \
8623579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        int childCount = SkInstanceCountHelper::gChildren->count();         \
8773e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        int count = SkInstanceCountHelper::gInstanceCount;                  \
8873e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        for (int i = 0; i < childCount; ++i) {                              \
8923579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com            count -= (*(*SkInstanceCountHelper::gChildren)[i])(level+1, cleanUp); \
904d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
9173e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        SkASSERT(count >= 0);                                               \
92b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com        if (gPrintInstCount && childCount > 0 && count > 0) {               \
9373e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
9473e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        }                                                                   \
9523579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        if (cleanUp) {                                                      \
9623579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com            delete SkInstanceCountHelper::gChildren;                        \
9723579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com            SkInstanceCountHelper::gChildren = NULL;                        \
9823579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        }                                                                   \
9973e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        return SkInstanceCountHelper::gInstanceCount;                       \
1004d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    }                                                                       \
1014d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
102a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com    static void AddInstChild(templateType SkInstanceCountHelper::PFCheckInstCnt \
1034d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                       childCheckInstCnt) { \
10423579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        if (CheckInstanceCount != childCheckInstCnt &&                      \
10523579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com            NULL != SkInstanceCountHelper::gChildren) {                     \
10623579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com            SkInstanceCountHelper::gChildren->push_back(childCheckInstCnt); \
1074d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
108977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com    }
109977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
1104d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DEFINE_INST_COUNT(className)                                     \
1114d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    int32_t className::SkInstanceCountHelper::gInstanceCount = 0;           \
1124d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    bool className::SkInstanceCountHelper::gInited = false;                 \
11323579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com    SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>*             \
11423579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com                        className::SkInstanceCountHelper::gChildren = NULL;
115977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
1164fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)              \
1174fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com    templateInfo int32_t className::SkInstanceCountHelper::gInstanceCount = 0;\
1184fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com    templateInfo bool className::SkInstanceCountHelper::gInited = false;    \
1194fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com    templateInfo                                                            \
1204fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com        SkTArray<typename className::SkInstanceCountHelper::PFCheckInstCnt>*\
1214fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com                      className::SkInstanceCountHelper::gChildren = NULL;
1224fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com
123977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#else
1244d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT(className)
125a22e2117e44efa4298dd0eb6df304a8166c8e9c3robertphillips@google.com#define SK_DECLARE_INST_COUNT_TEMPLATE(className)
1264d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT_ROOT(className)
1274d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DEFINE_INST_COUNT(className)
1284fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
129977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#endif
130977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
131977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#endif // SkInstCnt_DEFINED
132