Add missing pnacl libraries and headers and tools.
[chromium-blink-merge.git] / base / debug / leak_tracker.h
blob93cea39a0a3c1ff726fba829cef5bfc39599277f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef BASE_DEBUG_LEAK_TRACKER_H_
6 #define BASE_DEBUG_LEAK_TRACKER_H_
8 // Only enable leak tracking in debug builds.
9 #ifndef NDEBUG
10 #define ENABLE_LEAK_TRACKER
11 #endif
13 #ifdef ENABLE_LEAK_TRACKER
14 #include "base/containers/linked_list.h"
15 #include "base/debug/stack_trace.h"
16 #include "base/logging.h"
17 #endif // ENABLE_LEAK_TRACKER
19 // LeakTracker is a helper to verify that all instances of a class
20 // have been destroyed.
22 // It is particularly useful for classes that are bound to a single thread --
23 // before destroying that thread, one can check that there are no remaining
24 // instances of that class.
26 // For example, to enable leak tracking for class net::URLRequest, start by
27 // adding a member variable of type LeakTracker<net::URLRequest>.
29 // class URLRequest {
30 // ...
31 // private:
32 // base::LeakTracker<URLRequest> leak_tracker_;
33 // };
36 // Next, when we believe all instances of net::URLRequest have been deleted:
38 // LeakTracker<net::URLRequest>::CheckForLeaks();
40 // Should the check fail (because there are live instances of net::URLRequest),
41 // then the allocation callstack for each leaked instances is dumped to
42 // the error log.
44 // If ENABLE_LEAK_TRACKER is not defined, then the check has no effect.
46 namespace base {
47 namespace debug {
49 #ifndef ENABLE_LEAK_TRACKER
51 // If leak tracking is disabled, do nothing.
52 template<typename T>
53 class LeakTracker {
54 public:
55 ~LeakTracker() {}
56 static void CheckForLeaks() {}
57 static int NumLiveInstances() { return -1; }
60 #else
62 // If leak tracking is enabled we track where the object was allocated from.
64 template<typename T>
65 class LeakTracker : public LinkNode<LeakTracker<T> > {
66 public:
67 LeakTracker() {
68 instances()->Append(this);
71 ~LeakTracker() {
72 this->RemoveFromList();
75 static void CheckForLeaks() {
76 // Walk the allocation list and print each entry it contains.
77 size_t count = 0;
79 // Copy the first 3 leak allocation callstacks onto the stack.
80 // This way if we hit the CHECK() in a release build, the leak
81 // information will be available in mini-dump.
82 const size_t kMaxStackTracesToCopyOntoStack = 3;
83 StackTrace stacktraces[kMaxStackTracesToCopyOntoStack];
85 for (LinkNode<LeakTracker<T> >* node = instances()->head();
86 node != instances()->end();
87 node = node->next()) {
88 StackTrace& allocation_stack = node->value()->allocation_stack_;
90 if (count < kMaxStackTracesToCopyOntoStack)
91 stacktraces[count] = allocation_stack;
93 ++count;
94 if (LOG_IS_ON(ERROR)) {
95 LOG_STREAM(ERROR) << "Leaked " << node << " which was allocated by:";
96 allocation_stack.OutputToStream(&LOG_STREAM(ERROR));
100 CHECK_EQ(0u, count);
102 // Hack to keep |stacktraces| and |count| alive (so compiler
103 // doesn't optimize it out, and it will appear in mini-dumps).
104 if (count == 0x1234) {
105 for (size_t i = 0; i < kMaxStackTracesToCopyOntoStack; ++i)
106 stacktraces[i].PrintBacktrace();
110 static int NumLiveInstances() {
111 // Walk the allocation list and count how many entries it has.
112 int count = 0;
113 for (LinkNode<LeakTracker<T> >* node = instances()->head();
114 node != instances()->end();
115 node = node->next()) {
116 ++count;
118 return count;
121 private:
122 // Each specialization of LeakTracker gets its own static storage.
123 static LinkedList<LeakTracker<T> >* instances() {
124 static LinkedList<LeakTracker<T> > list;
125 return &list;
128 StackTrace allocation_stack_;
131 #endif // ENABLE_LEAK_TRACKER
133 } // namespace debug
134 } // namespace base
136 #endif // BASE_DEBUG_LEAK_TRACKER_H_