SkInstCnt.h revision ab1c13864df34aecfd4840ea7d1e4f8730b44f4e
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 * At the end of an application a call to all the "root" objects'
184d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com * CheckInstanceCount methods should be made
19977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com */
204e23068b374023d43c4c725138d523721d975892bsalomon@google.com#include "SkTypes.h"
21594dd3cd78e2f970d53bb0934fbbb63b41e1d40ccaryclark@google.com
224e23068b374023d43c4c725138d523721d975892bsalomon@google.com#if SK_ENABLE_INST_COUNT
234d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#include "SkTArray.h"
24c9ab987efcb7e8b69237d565f73c28c137610232djsollen@google.com#include "SkThread_platform.h"
254d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
26b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.comextern bool gPrintInstCount;
27b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com
2897fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com// The non-root classes just register themselves with their parent
294d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT(className)                                    \
304d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    SK_DECLARE_INST_COUNT_INTERNAL(className,                               \
31ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org                                   INHERITED::AddInstChild(CheckInstanceCount);)
324d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
3397fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com// The root classes registers a function to print out the memory stats when
3497fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com// the app ends
354d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DECLARE_INST_COUNT_ROOT(className)                               \
36ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org    SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);)
374d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
38ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep)                 \
394d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    class SkInstanceCountHelper {                                           \
404d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    public:                                                                 \
4123579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        typedef int (*PFCheckInstCnt)(int level, bool cleanUp);             \
424d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        SkInstanceCountHelper() {                                           \
43ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            static bool gInited;                                            \
444d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            if (!gInited) {                                                 \
454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                initStep                                                    \
46ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org                GetChildren() = new SkTArray<PFCheckInstCnt>;               \
474d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                gInited = true;                                             \
484d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com            }                                                               \
49ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            sk_atomic_inc(GetInstanceCountPtr());                           \
504d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
514d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
52e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com        SkInstanceCountHelper(const SkInstanceCountHelper&) {               \
53ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            sk_atomic_inc(GetInstanceCountPtr());                           \
544d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
554d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
564d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        ~SkInstanceCountHelper() {                                          \
57ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            sk_atomic_dec(GetInstanceCountPtr());                           \
58ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        }                                                                   \
59ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org                                                                            \
60ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        static int32_t* GetInstanceCountPtr() {                             \
61ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            static int32_t gInstanceCount;                                  \
62ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            return &gInstanceCount;                                         \
63ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        }                                                                   \
64ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org                                                                            \
65ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        static SkTArray<PFCheckInstCnt>*& GetChildren() {                   \
66ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            static SkTArray<PFCheckInstCnt>* gChildren;                     \
67ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            return gChildren;                                               \
684d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
694d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
704d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    } fInstanceCountHelper;                                                 \
714d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
724da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    static int32_t GetInstanceCount() {                                     \
73ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        return *SkInstanceCountHelper::GetInstanceCountPtr();               \
744da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    }                                                                       \
754da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com                                                                            \
7697fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com    static void exitPrint() {                                               \
7723579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        CheckInstanceCount(0, true);                                        \
7897fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com    }                                                                       \
7997fafe1b5ec06b470d36ea5cd98fe7bf2c143491robertphillips@google.com                                                                            \
8023579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com    static int CheckInstanceCount(int level = 0, bool cleanUp = false) {    \
81ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        if (gPrintInstCount && 0 != GetInstanceCount()) {                   \
8273e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            SkDebugf("%*c Leaked %s: %d\n",                                 \
8315e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com                     4*level, ' ', #className,                              \
84ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org                     GetInstanceCount());                                   \
854d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
86ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        if (NULL == SkInstanceCountHelper::GetChildren()) {                 \
87ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            return GetInstanceCount();                                      \
8823579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        }                                                                   \
89ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        SkTArray<int (*)(int, bool)>* children =                            \
90ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            SkInstanceCountHelper::GetChildren();                           \
91ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        int childCount = children->count();                                 \
92ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        int count = GetInstanceCount();                                     \
9373e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        for (int i = 0; i < childCount; ++i) {                              \
94ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            count -= (*(*children)[i])(level+1, cleanUp);                   \
954d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
9673e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        SkASSERT(count >= 0);                                               \
97b74af872cc1ce45768df3ae03fa86ad3ed76b582robertphillips@google.com        if (gPrintInstCount && childCount > 0 && count > 0) {               \
9873e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com            SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count);    \
9973e19fb1ba2562048c6987272c8d73eee6a44242reed@google.com        }                                                                   \
10023579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        if (cleanUp) {                                                      \
101ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            delete children;                                                \
102ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            SkInstanceCountHelper::GetChildren() = NULL;                    \
10323579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        }                                                                   \
104ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org        return GetInstanceCount();                                          \
1054d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    }                                                                       \
1064d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com                                                                            \
107ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org    static void AddInstChild(int (*childCheckInstCnt)(int, bool)) {         \
10823579275c7f544763d074d90563c4b1e567ab041robertphillips@google.com        if (CheckInstanceCount != childCheckInstCnt &&                      \
109ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            NULL != SkInstanceCountHelper::GetChildren()) {                 \
110ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org            SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \
1114d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com        }                                                                   \
112977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com    }
113977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
114977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#else
115ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org// Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by
116ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org// causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays
117ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org// compiling.
118ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org#define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); }
119ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org#define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { }
120ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org#endif
121ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org
122ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org// Following are deprecated. They are defined only for backwards API compatibility.
123ab1c13864df34aecfd4840ea7d1e4f8730b44f4ecommit-bot@chromium.org#define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className)
1244d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com#define SK_DEFINE_INST_COUNT(className)
1254fa9c9f9b42c22bffff3b2eb3fcf7f16a2ab2948robertphillips@google.com#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className)
126977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
127977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#endif // SkInstCnt_DEFINED
128