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