SkInstCnt.h revision b74af872cc1ce45768df3ae03fa86ad3ed76b582
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/*
13977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@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
224d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#include "SkTArray.h"
234d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
24b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.comextern bool gPrintInstCount;
25b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com
264d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT(className)                                    \
274d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
284d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                INHERITED::AddInstChild(CheckInstanceCount);)
294d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
304d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT_ROOT(className)                               \
314d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    SK_DECLARE_INST_COUNT_INTERNAL(className, ;)
324d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
334d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep)                 \
344d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    class SkInstanceCountHelper {                                           \
354d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    public:                                                                 \
3673e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        typedef int (*PFCheckInstCnt)(int level);                           \
374d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        SkInstanceCountHelper() {                                           \
384d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            if (!gInited) {                                                 \
394d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                initStep                                                    \
404d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                gInited = true;                                             \
414d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            }                                                               \
424d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            gInstanceCount++;                                               \
434d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
444d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        SkInstanceCountHelper(const SkInstanceCountHelper& other) {         \
464d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            gInstanceCount++;                                               \
474d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
484d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
494d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        ~SkInstanceCountHelper() {                                          \
504d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            gInstanceCount--;                                               \
514d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
524d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
534d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        static int32_t gInstanceCount;                                      \
544d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        static bool gInited;                                                \
554d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        static SkTArray<PFCheckInstCnt> gChildren;                          \
564d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    } fInstanceCountHelper;                                                 \
574d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
584da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    static int32_t GetInstanceCount() {                                     \
594da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        return SkInstanceCountHelper::gInstanceCount;                       \
604da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    }                                                                       \
614da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com                                                                            \
6273e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com    static int CheckInstanceCount(int level = 0) {                          \
63b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com        if (gPrintInstCount && 0 != SkInstanceCountHelper::gInstanceCount) {\
6473e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            SkDebugf("%*c Leaked %s: %d\n",                                 \
6515e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com                     4*level, ' ', #className,                              \
664d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                     SkInstanceCountHelper::gInstanceCount);                \
674d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
6873e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        int childCount = SkInstanceCountHelper::gChildren.count();          \
6973e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        int count = SkInstanceCountHelper::gInstanceCount;                  \
7073e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        for (int i = 0; i < childCount; ++i) {                              \
7173e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            count -= (*SkInstanceCountHelper::gChildren[i])(level+1);       \
724d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
7373e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        SkASSERT(count >= 0);                                               \
74b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com        if (gPrintInstCount && childCount > 0 && count > 0) {               \
7573e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
7673e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        }                                                                   \
7773e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        return SkInstanceCountHelper::gInstanceCount;                       \
784d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    }                                                                       \
794d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
804d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    static void AddInstChild(SkInstanceCountHelper::PFCheckInstCnt          \
814d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                       childCheckInstCnt) { \
824d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        if (CheckInstanceCount != childCheckInstCnt) {                      \
834d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            SkInstanceCountHelper::gChildren.push_back(childCheckInstCnt);  \
844d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
85977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com    }
86977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
874d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DEFINE_INST_COUNT(className)                                     \
884d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    int32_t className::SkInstanceCountHelper::gInstanceCount = 0;           \
894d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    bool className::SkInstanceCountHelper::gInited = false;                 \
904d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    SkTArray<className::SkInstanceCountHelper::PFCheckInstCnt>              \
914d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                        className::SkInstanceCountHelper::gChildren;
92977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
93977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#else
944d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT(className)
954d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT_ROOT(className)
964d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DEFINE_INST_COUNT(className)
97977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#endif
98977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
99977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#endif // SkInstCnt_DEFINED
100