1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/core/SkInstCnt.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,142 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 + 1.12 +#ifndef SkInstCnt_DEFINED 1.13 +#define SkInstCnt_DEFINED 1.14 + 1.15 +/* 1.16 + * The instance counting system consists of three macros that create the 1.17 + * instance counting machinery. A class is added to the system by adding: 1.18 + * SK_DECLARE_INST_COUNT at the top of its declaration for derived classes 1.19 + * SK_DECLARE_INST_COUNT_ROOT at the top of its declaration for a root class 1.20 + * At the end of an application a call to all the "root" objects' 1.21 + * CheckInstanceCount methods should be made 1.22 + */ 1.23 +#include "SkTypes.h" 1.24 + 1.25 +#if SK_ENABLE_INST_COUNT 1.26 +// Static variables inside member functions below may be defined multiple times 1.27 +// if Skia is being used as a dynamic library. Instance counting should be on 1.28 +// only for static builds. See bug skia:2058. 1.29 +#if defined(SKIA_DLL) 1.30 +#error Instance counting works only when Skia is built as a static library. 1.31 +#endif 1.32 + 1.33 +#include "SkOnce.h" 1.34 +#include "SkTArray.h" 1.35 +#include "SkThread.h" 1.36 +extern bool gPrintInstCount; 1.37 + 1.38 +// The non-root classes just register themselves with their parent 1.39 +#define SK_DECLARE_INST_COUNT(className) \ 1.40 + SK_DECLARE_INST_COUNT_INTERNAL(className, \ 1.41 + INHERITED::AddInstChild(CheckInstanceCount);) 1.42 + 1.43 +// The root classes registers a function to print out the memory stats when 1.44 +// the app ends 1.45 +#define SK_DECLARE_INST_COUNT_ROOT(className) \ 1.46 + SK_DECLARE_INST_COUNT_INTERNAL(className, atexit(exitPrint);) 1.47 + 1.48 +#define SK_DECLARE_INST_COUNT_INTERNAL(className, initStep) \ 1.49 + class SkInstanceCountHelper { \ 1.50 + public: \ 1.51 + SkInstanceCountHelper() { \ 1.52 + SK_DECLARE_STATIC_ONCE(once); \ 1.53 + SkOnce(&once, init, 0); \ 1.54 + sk_atomic_inc(GetInstanceCountPtr()); \ 1.55 + } \ 1.56 + \ 1.57 + static void init(int) { \ 1.58 + initStep \ 1.59 + } \ 1.60 + \ 1.61 + SkInstanceCountHelper(const SkInstanceCountHelper&) { \ 1.62 + sk_atomic_inc(GetInstanceCountPtr()); \ 1.63 + } \ 1.64 + \ 1.65 + ~SkInstanceCountHelper() { \ 1.66 + sk_atomic_dec(GetInstanceCountPtr()); \ 1.67 + } \ 1.68 + \ 1.69 + static int32_t* GetInstanceCountPtr() { \ 1.70 + static int32_t gInstanceCount; \ 1.71 + return &gInstanceCount; \ 1.72 + } \ 1.73 + \ 1.74 + static SkTArray<int (*)(int, bool)>*& GetChildren() { \ 1.75 + static SkTArray<int (*)(int, bool)>* gChildren; \ 1.76 + return gChildren; \ 1.77 + } \ 1.78 + \ 1.79 + static SkBaseMutex& GetChildrenMutex() { \ 1.80 + SK_DECLARE_STATIC_MUTEX(childrenMutex); \ 1.81 + return childrenMutex; \ 1.82 + } \ 1.83 + \ 1.84 + } fInstanceCountHelper; \ 1.85 + \ 1.86 + static int32_t GetInstanceCount() { \ 1.87 + return *SkInstanceCountHelper::GetInstanceCountPtr(); \ 1.88 + } \ 1.89 + \ 1.90 + static void exitPrint() { \ 1.91 + CheckInstanceCount(0, true); \ 1.92 + } \ 1.93 + \ 1.94 + static int CheckInstanceCount(int level = 0, bool cleanUp = false) { \ 1.95 + if (gPrintInstCount && 0 != GetInstanceCount()) { \ 1.96 + SkDebugf("%*c Leaked %s: %d\n", \ 1.97 + 4*level, ' ', #className, \ 1.98 + GetInstanceCount()); \ 1.99 + } \ 1.100 + if (NULL == SkInstanceCountHelper::GetChildren()) { \ 1.101 + return GetInstanceCount(); \ 1.102 + } \ 1.103 + SkTArray<int (*)(int, bool)>* children = \ 1.104 + SkInstanceCountHelper::GetChildren(); \ 1.105 + int childCount = children->count(); \ 1.106 + int count = GetInstanceCount(); \ 1.107 + for (int i = 0; i < childCount; ++i) { \ 1.108 + count -= (*(*children)[i])(level+1, cleanUp); \ 1.109 + } \ 1.110 + SkASSERT(count >= 0); \ 1.111 + if (gPrintInstCount && childCount > 0 && count > 0) { \ 1.112 + SkDebugf("%*c Leaked ???: %d\n", 4*(level + 1), ' ', count); \ 1.113 + } \ 1.114 + if (cleanUp) { \ 1.115 + delete children; \ 1.116 + SkInstanceCountHelper::GetChildren() = NULL; \ 1.117 + } \ 1.118 + return GetInstanceCount(); \ 1.119 + } \ 1.120 + \ 1.121 + static void AddInstChild(int (*childCheckInstCnt)(int, bool)) { \ 1.122 + if (CheckInstanceCount != childCheckInstCnt) { \ 1.123 + SkAutoMutexAcquire ama(SkInstanceCountHelper::GetChildrenMutex()); \ 1.124 + if (NULL == SkInstanceCountHelper::GetChildren()) { \ 1.125 + SkInstanceCountHelper::GetChildren() = \ 1.126 + new SkTArray<int (*)(int, bool)>; \ 1.127 + } \ 1.128 + SkInstanceCountHelper::GetChildren()->push_back(childCheckInstCnt); \ 1.129 + } \ 1.130 + } 1.131 + 1.132 +#else 1.133 +// Typically SK_ENABLE_INST_COUNT=0. Make sure the class declares public typedef INHERITED by 1.134 +// causing a compile-time error if the typedef is missing. This way SK_ENABLE_INST_COUNT=1 stays 1.135 +// compiling. 1.136 +#define SK_DECLARE_INST_COUNT(className) static void AddInstChild() { INHERITED::AddInstChild(); } 1.137 +#define SK_DECLARE_INST_COUNT_ROOT(className) static void AddInstChild() { } 1.138 +#endif 1.139 + 1.140 +// Following are deprecated. They are defined only for backwards API compatibility. 1.141 +#define SK_DECLARE_INST_COUNT_TEMPLATE(className) SK_DECLARE_INST_COUNT(className) 1.142 +#define SK_DEFINE_INST_COUNT(className) 1.143 +#define SK_DEFINE_INST_COUNT_TEMPLATE(templateInfo, className) 1.144 + 1.145 +#endif // SkInstCnt_DEFINED