OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2012 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #ifndef SkInstCnt_DEFINED | |
9 #define SkInstCnt_DEFINED | |
10 | |
11 /* To count all instances of T, including all subclasses of T, | |
12 * add SK_DECLARE_INST_COUNT(T) to T's class definition. | |
13 * If you want to print out counts of leaked instances, set gPrintInstCount to t
rue in main(). | |
14 * | |
15 * E.g. | |
16 * struct Base { SK_DECLARE_INST_COUNT(Base) }; | |
17 * struct A : public Base {}; | |
18 * struct SubBase : public Base { SK_DECLARE_INST_COUNT(SubBase); } | |
19 * struct B : public SubBase {}; | |
20 * | |
21 * If gPrintInstCount is true, at the program exit you will see something like: | |
22 * Base: <N> leaked instances | |
23 * SubBase: <M> leaked instances | |
24 * where N >= M. Leaked instances of A count against Base; leaked instances of
B count against | |
25 * both SubBase and Base. | |
26 * | |
27 * If SK_ENABLE_INST_COUNT is not defined or defined to 0, or we're in a shared
library build, | |
28 * this entire system is compiled away to a noop. | |
29 */ | |
30 | |
31 #include "SkTypes.h" | |
32 | |
33 #if SK_ENABLE_INST_COUNT && !defined(SKIA_DLL) // See skia:2058 for why we noop
on shared builds. | |
34 #include "SkThread.h" | |
35 #include <stdlib.h> | |
36 | |
37 #define SK_DECLARE_INST_COUNT(T) \ | |
38 static const char* InstCountClassName() { return #T; } \ | |
39 SkInstCount<T, T::InstCountClassName> fInstCnt; \ | |
40 static int32_t GetInstanceCount() { return SkInstCount<T, InstCountClass
Name>::Count(); } | |
41 | |
42 extern bool gPrintInstCount; | |
43 | |
44 template <typename T, const char*(Name)()> | |
45 class SkInstCount { | |
46 public: | |
47 SkInstCount() { Inc(); } | |
48 SkInstCount(const SkInstCount&) { Inc(); } | |
49 ~SkInstCount() { sk_atomic_dec(&gCount); } | |
50 | |
51 SkInstCount& operator==(const SkInstCount&) { return *this; } // == can'
t change the count. | |
52 | |
53 static void Inc() { | |
54 // If it's the first time we go from 0 to 1, register to print leaks
at process exit. | |
55 if (0 == sk_atomic_inc(&gCount) && sk_atomic_cas(&gRegistered, 0, 1)
) { | |
56 atexit(PrintAtExit); | |
57 } | |
58 } | |
59 | |
60 static void PrintAtExit() { | |
61 int32_t leaks = Count(); | |
62 if (gPrintInstCount && leaks > 0) { | |
63 SkDebugf("Leaked %s: %d\n", Name(), leaks); | |
64 } | |
65 } | |
66 | |
67 // FIXME: Used publicly by unit tests. Seems like a bad idea in a DM wo
rld. | |
68 static int32_t Count() { return sk_acquire_load(&gCount); } | |
69 | |
70 private: | |
71 static int32_t gCount, gRegistered; | |
72 }; | |
73 // As template values, these will be deduplicated. (No one-definition rule
problems.) | |
74 template <typename T, const char*(Name)()> int32_t SkInstCount<T, Name>::gCo
unt = 0; | |
75 template <typename T, const char*(Name)()> int32_t SkInstCount<T, Name>::gRe
gistered = 0; | |
76 #else | |
77 #define SK_DECLARE_INST_COUNT(T) | |
78 #endif | |
79 | |
80 void SkInstCountPrintLeaksOnExit(); | |
81 | |
82 #endif // SkInstCnt_DEFINED | |
OLD | NEW |