13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/tracked_objects.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <math.h>
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/format_macros.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta;
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace tracked_objects {
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A TLS slot to the TrackRegistry for the current thread.
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenbase::ThreadLocalStorage::Slot ThreadData::tls_index_(base::LINKER_INITIALIZED);
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A global state variable to prevent repeated initialization during tests.
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottAutoTracking::State AutoTracking::state_ = AutoTracking::kNeverBeenRun;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Death data tallies durations when a death takes place.
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DeathData::RecordDeath(const TimeDelta& duration) {
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ++count_;
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  life_duration_ += duration;
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 milliseconds = duration.InMilliseconds();
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  square_duration_ += milliseconds * milliseconds;
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint DeathData::AverageMsDuration() const {
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return static_cast<int>(life_duration_.InMilliseconds() / count_);
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdouble DeathData::StandardDeviation() const {
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  double average = AverageMsDuration();
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  double variance = static_cast<float>(square_duration_)/count_
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                    - average * average;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return sqrt(variance);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DeathData::AddDeathData(const DeathData& other) {
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  count_ += other.count_;
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  life_duration_ += other.life_duration_;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  square_duration_ += other.square_duration_;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DeathData::Write(std::string* output) const {
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!count_)
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (1 == count_) {
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "(1)Life in %dms ", AverageMsDuration());
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "(%d)Lives %dms/life ",
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        count_, AverageMsDuration());
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DeathData::Clear() {
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  count_ = 0;
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  life_duration_ = TimeDelta();
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  square_duration_ = 0;
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBirthOnThread::BirthOnThread(const Location& location)
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : location_(location),
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      birth_thread_(ThreadData::current()) { }
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBirths::Births(const Location& location)
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : BirthOnThread(location),
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      birth_count_(1) { }
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ThreadData maintains the central data for all births and death.
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottThreadData* ThreadData::first_ = NULL;
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbase::Lock ThreadData::list_lock_;
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottThreadData::Status ThreadData::status_ = ThreadData::UNINITIALIZED;
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochThreadData::ThreadData() : next_(NULL) {
94201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // This shouldn't use the MessageLoop::current() LazyInstance since this might
95201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // be used on a non-joinable thread.
96201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // http://crbug.com/62728
97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton;
98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  message_loop_ = MessageLoop::current();
99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickThreadData::~ThreadData() {}
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottThreadData* ThreadData::current() {
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!tls_index_.initialized())
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return NULL;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData* registry = static_cast<ThreadData*>(tls_index_.Get());
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!registry) {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We have to create a new registry for ThreadData.
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool too_late_to_create = false;
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      registry = new ThreadData;
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::AutoLock lock(list_lock_);
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Use lock to insure we have most recent status.
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!IsActive()) {
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        too_late_to_create = true;
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Use lock to insert into list.
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        registry->next_ = first_;
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        first_ = registry;
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }  // Release lock.
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (too_late_to_create) {
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delete registry;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      registry = NULL;
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tls_index_.Set(registry);
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return registry;
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Do mininimal fixups for searching function names.
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic std::string UnescapeQuery(const std::string& query) {
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string result;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < query.size(); i++) {
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char next = query[i];
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if ('%' == next && i + 2 < query.size()) {
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      std::string hex = query.substr(i + 1, 2);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      char replacement = '\0';
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Only bother with "<", ">", and " ".
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (LowerCaseEqualsASCII(hex, "3c"))
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        replacement ='<';
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else if (LowerCaseEqualsASCII(hex, "3e"))
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        replacement = '>';
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else if (hex == "20")
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        replacement = ' ';
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (replacement) {
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        next = replacement;
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        i += 2;
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    result.push_back(next);
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return result;
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::WriteHTML(const std::string& query, std::string* output) {
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ThreadData::IsActive())
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;  // Not yet initialized.
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ThreadData::current());
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  output->append("<html><head><title>About Tasks");
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string escaped_query = UnescapeQuery(query);
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!escaped_query.empty())
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    output->append(" - " + escaped_query);
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->append("</title></head><body><pre>");
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DataCollector collected_data;  // Gather data.
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  collected_data.AddListOfLivingObjects();  // Add births that are still alive.
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Data Gathering is complete. Now to sort/process/render.
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DataCollector::Collection* collection = collected_data.collection();
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Create filtering and sort comparison object.
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Comparator comparator;
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  comparator.ParseQuery(escaped_query);
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Filter out acceptable (matching) instances.
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DataCollector::Collection match_array;
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (DataCollector::Collection::iterator it = collection->begin();
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != collection->end(); ++it) {
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (comparator.Acceptable(*it))
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      match_array.push_back(*it);
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  comparator.Sort(&match_array);
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WriteHTMLTotalAndSubtotals(match_array, comparator, output);
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  comparator.Clear();  // Delete tiebreaker_ instances.
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->append("</pre>");
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const char* help_string = "The following are the keywords that can be used to"
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "sort and aggregate the data, or to select data.<br><ul>"
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>count</b> Number of instances seen."
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>duration</b> Duration in ms from construction to descrution."
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>birth</b> Thread on which the task was constructed."
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>death</b> Thread on which the task was run and deleted."
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>file</b> File in which the task was contructed."
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>function</b> Function in which the task was constructed."
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>line</b> Line number of the file in which the task was constructed."
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "</ul><br>"
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "As examples:<ul>"
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>about:tasks/file</b> would sort the above data by file, and"
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " aggregate data on a per-file basis."
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>about:tasks/file=Dns</b> would only list data for tasks constructed"
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " in a file containing the text |Dns|."
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "<li><b>about:tasks/birth/death</b> would sort the above list by birth"
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " thread, and then by death thread, and would aggregate data for each pair"
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " of lifetime events."
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "</ul>"
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " The data can be reset to zero (discarding all births, deaths, etc.) using"
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " <b>about:tasks/reset</b>. The existing stats will be displayed, but the"
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " internal stats will be set to zero, and start accumulating afresh. This"
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " option is very helpful if you only wish to consider tasks created after"
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " some point in time.<br><br>"
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "If you wish to monitor Renderer events, be sure to run in --single-process"
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    " mode.";
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->append(help_string);
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->append("</body></html>");
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::WriteHTMLTotalAndSubtotals(
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const DataCollector::Collection& match_array,
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const Comparator& comparator,
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string* output) {
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!match_array.size()) {
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    output->append("There were no tracked matches.");
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Aggregate during printing
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Aggregation totals;
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0; i < match_array.size(); ++i) {
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      totals.AddDeathSnapshot(match_array[i]);
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    output->append("Aggregate Stats: ");
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    totals.Write(output);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    output->append("<hr><hr>");
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Aggregation subtotals;
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (size_t i = 0; i < match_array.size(); ++i) {
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (0 == i || !comparator.Equivalent(match_array[i - 1],
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           match_array[i])) {
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Print group's defining characteristics.
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        comparator.WriteSortGrouping(match_array[i], output);
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        output->append("<br><br>");
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      comparator.WriteSnapshot(match_array[i], output);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      output->append("<br>");
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      subtotals.AddDeathSnapshot(match_array[i]);
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (i + 1 >= match_array.size() ||
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          !comparator.Equivalent(match_array[i],
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                 match_array[i + 1])) {
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // Print aggregate stats for the group.
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        output->append("<br>");
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        subtotals.Write(output);
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        output->append("<br><hr><br>");
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        subtotals.Clear();
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBirths* ThreadData::TallyABirth(const Location& location) {
270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  {
271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // This shouldn't use the MessageLoop::current() LazyInstance since this
272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // might be used on a non-joinable thread.
273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // http://crbug.com/62728
274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton;
275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (!message_loop_)  // In case message loop wasn't yet around...
276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      message_loop_ = MessageLoop::current();  // Find it now.
277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  BirthMap::iterator it = birth_map_.find(location);
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != birth_map_.end()) {
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    it->second->RecordBirth();
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return it->second;
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Births* tracker = new Births(location);
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Lock since the map may get relocated now, and other threads sometimes
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // snapshot it (but they lock before copying it).
28872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_map_[location] = tracker;
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return tracker;
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::TallyADeath(const Births& lifetimes,
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             const TimeDelta& duration) {
295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  {
296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // http://crbug.com/62728
297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    base::ThreadRestrictions::ScopedAllowSingleton scoped_allow_singleton;
298201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (!message_loop_)  // In case message loop wasn't yet around...
299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      message_loop_ = MessageLoop::current();  // Find it now.
300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeathMap::iterator it = death_map_.find(&lifetimes);
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it != death_map_.end()) {
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    it->second.RecordDeath(duration);
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);  // Lock since the map may get relocated now.
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  death_map_[&lifetimes].RecordDeath(duration);
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottThreadData* ThreadData::first() {
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(list_lock_);
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return first_;
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string ThreadData::ThreadName() const {
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (message_loop_)
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return message_loop_->thread_name();
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return "ThreadWithoutMessageLoop";
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This may be called from another thread.
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::SnapshotBirthMap(BirthMap *output) const {
32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (BirthMap::const_iterator it = birth_map_.begin();
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != birth_map_.end(); ++it)
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    (*output)[it->first] = it->second;
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This may be called from another thread.
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::SnapshotDeathMap(DeathMap *output) const {
33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (DeathMap::const_iterator it = death_map_.begin();
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != death_map_.end(); ++it)
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    (*output)[it->first] = it->second;
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::ResetAllThreadData() {
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData* my_list = ThreadData::current()->first();
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (ThreadData* thread_data = my_list;
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       thread_data;
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       thread_data = thread_data->next())
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_data->Reset();
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::Reset() {
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(lock_);
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (DeathMap::iterator it = death_map_.begin();
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != death_map_.end(); ++it)
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    it->second.Clear();
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (BirthMap::iterator it = birth_map_.begin();
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != birth_map_.end(); ++it)
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    it->second->Clear();
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef OS_WIN
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// A class used to count down which is accessed by several threads.  This is
3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// used to make sure RunOnAllThreads() actually runs a task on the expected
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// count of threads.
3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ThreadData::ThreadSafeDownCounter {
3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Constructor sets the count, once and for all.
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  explicit ThreadSafeDownCounter(size_t count);
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Decrement the count, and return true if we hit zero.  Also delete this
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // instance automatically when we hit zero.
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool LastCaller();
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  size_t remaining_count_;
37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::Lock lock_;  // protect access to remaining_count_.
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickThreadData::ThreadSafeDownCounter::ThreadSafeDownCounter(size_t count)
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : remaining_count_(count) {
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK_GT(remaining_count_, 0u);
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool ThreadData::ThreadSafeDownCounter::LastCaller() {
3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  {
38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock lock(lock_);
3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (--remaining_count_)
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return false;
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }  // Release lock, so we can delete everything in this instance.
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete this;
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return true;
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// A Task class that runs a static method supplied, and checks to see if this
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// is the last tasks instance (on last thread) that will run the method.
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// IF this is the last run, then the supplied event is signalled.
3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass ThreadData::RunTheStatic : public Task {
3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick public:
3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  typedef void (*FunctionPointer)();
3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  RunTheStatic(FunctionPointer function,
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               HANDLE completion_handle,
4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick               ThreadSafeDownCounter* counter);
4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Run the supplied static method, and optionally set the event.
4033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void Run();
4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick private:
4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FunctionPointer function_;
4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  HANDLE completion_handle_;
4083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure enough tasks are called before completion is signaled.
4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ThreadSafeDownCounter* counter_;
4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DISALLOW_COPY_AND_ASSIGN(RunTheStatic);
4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick};
4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickThreadData::RunTheStatic::RunTheStatic(FunctionPointer function,
4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       HANDLE completion_handle,
4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       ThreadSafeDownCounter* counter)
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : function_(function),
4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      completion_handle_(completion_handle),
4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      counter_(counter) {
4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ThreadData::RunTheStatic::Run() {
4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  function_();
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (counter_->LastCaller())
4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    SetEvent(completion_handle_);
4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(jar): This should use condition variables, and be cross platform.
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::RunOnAllThreads(void (*function)()) {
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData* list = first();  // Get existing list.
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::vector<MessageLoop*> message_loops;
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (ThreadData* it = list; it; it = it->next()) {
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (current() != it && it->message_loop())
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      message_loops.push_back(it->message_loop());
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadSafeDownCounter* counter =
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    new ThreadSafeDownCounter(message_loops.size() + 1);  // Extra one for us!
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HANDLE completion_handle = CreateEvent(NULL, false, false, NULL);
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Tell all other threads to run.
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < message_loops.size(); ++i)
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    message_loops[i]->PostTask(
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        FROM_HERE, new RunTheStatic(function, completion_handle, counter));
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Also run Task on our thread.
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RunTheStatic local_task(function, completion_handle, counter);
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  local_task.Run();
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WaitForSingleObject(completion_handle, INFINITE);
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int ret_val = CloseHandle(completion_handle);
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ret_val);
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif  // OS_WIN
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ThreadData::StartTracking(bool status) {
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef TRACK_ALL_TASK_OBJECTS
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;  // Not compiled in.
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!status) {
46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock lock(list_lock_);
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(status_ == ACTIVE || status_ == SHUTDOWN);
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    status_ = SHUTDOWN;
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
46972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(list_lock_);
470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_EQ(UNINITIALIZED, status_);
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(tls_index_.Initialize(NULL));
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  status_ = ACTIVE;
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ThreadData::IsActive() {
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return status_ == ACTIVE;
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef OS_WIN
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::ShutdownMultiThreadTracking() {
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Using lock, guarantee that no new ThreadData instances will be created.
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!StartTracking(false))
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RunOnAllThreads(ShutdownDisablingFurtherTracking);
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Now the *only* threads that might change the database are the threads with
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // no messages loops.  They might still be adding data to their birth records,
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // but since no objects are deleted on those threads, there will be no further
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // access to to cross-thread data.
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We could do a cleanup on all threads except for the ones without
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // MessageLoops, but we won't bother doing cleanup (destruction of data) yet.
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return;
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::ShutdownSingleThreadedCleanup() {
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We must be single threaded... but be careful anyway.
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!StartTracking(false))
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData* thread_data_list;
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  {
50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock lock(list_lock_);
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_data_list = first_;
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    first_ = NULL;
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (thread_data_list) {
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ThreadData* next_thread_data = thread_data_list;
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_data_list = thread_data_list->next();
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (BirthMap::iterator it = next_thread_data->birth_map_.begin();
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         next_thread_data->birth_map_.end() != it; ++it)
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delete it->second;  // Delete the Birth Records.
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_thread_data->birth_map_.clear();
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    next_thread_data->death_map_.clear();
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete next_thread_data;  // Includes all Death Records.
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(tls_index_.initialized());
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tls_index_.Free();
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!tls_index_.initialized());
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  status_ = UNINITIALIZED;
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ThreadData::ShutdownDisablingFurtherTracking() {
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Redundantly set status SHUTDOWN on this thread.
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!StartTracking(false))
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Individual 3-tuple of birth (place and thread) along with death thread, and
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the accumulated stats for instances (DeathData).
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSnapshot::Snapshot(const BirthOnThread& birth_on_thread,
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   const ThreadData& death_thread,
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   const DeathData& death_data)
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : birth_(&birth_on_thread),
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      death_thread_(&death_thread),
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      death_data_(death_data) {
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSnapshot::Snapshot(const BirthOnThread& birth_on_thread, int count)
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : birth_(&birth_on_thread),
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      death_thread_(NULL),
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      death_data_(DeathData(count)) {
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string Snapshot::DeathThreadName() const {
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (death_thread_)
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return death_thread_->ThreadName();
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return "Still_Alive";
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Snapshot::Write(std::string* output) const {
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  death_data_.Write(output);
5633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::StringAppendF(output, "%s->%s ",
5643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      birth_->birth_thread()->ThreadName().c_str(),
5653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      death_thread_->ThreadName().c_str());
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_->location().Write(true, true, output);
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Snapshot::Add(const Snapshot& other) {
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  death_data_.AddDeathData(other.death_data_);
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// DataCollector
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottDataCollector::DataCollector() {
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(ThreadData::IsActive());
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get an unchanging copy of a ThreadData list.
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData* my_list = ThreadData::current()->first();
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  count_of_contributing_threads_ = 0;
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (ThreadData* thread_data = my_list;
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       thread_data;
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       thread_data = thread_data->next()) {
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++count_of_contributing_threads_;
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Gather data serially.  A different constructor could be used to do in
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // parallel, and then invoke an OnCompletion task.
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This hackish approach *can* get some slighly corrupt tallies, as we are
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // grabbing values without the protection of a lock, but it has the advantage
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of working even with threads that don't have message loops.  If a user
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sees any strangeness, they can always just run their stats gathering a
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // second time.
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(jar): Provide version that gathers stats safely via PostTask in all
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // cases where thread_data supplies a message_loop to post to.  Be careful to
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // handle message_loops that are destroyed!?!
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (ThreadData* thread_data = my_list;
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       thread_data;
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       thread_data = thread_data->next()) {
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    Append(*thread_data);
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6063345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickDataCollector::~DataCollector() {
6073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DataCollector::Append(const ThreadData& thread_data) {
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get copy of data (which is done under ThreadData's lock).
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData::BirthMap birth_map;
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  thread_data.SnapshotBirthMap(&birth_map);
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ThreadData::DeathMap death_map;
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  thread_data.SnapshotDeathMap(&death_map);
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Use our lock to protect our accumulation activity.
61772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::AutoLock lock(accumulation_lock_);
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(count_of_contributing_threads_);
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (ThreadData::DeathMap::const_iterator it = death_map.begin();
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != death_map.end(); ++it) {
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    collection_.push_back(Snapshot(*it->first, thread_data, it->second));
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    global_birth_count_[it->first] -= it->first->birth_count();
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (ThreadData::BirthMap::const_iterator it = birth_map.begin();
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != birth_map.end(); ++it) {
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    global_birth_count_[it->second] += it->second->birth_count();
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  --count_of_contributing_threads_;
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottDataCollector::Collection* DataCollector::collection() {
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!count_of_contributing_threads_);
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return &collection_;
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DataCollector::AddListOfLivingObjects() {
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!count_of_contributing_threads_);
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (BirthCount::iterator it = global_birth_count_.begin();
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != global_birth_count_.end(); ++it) {
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (it->second > 0)
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      collection_.push_back(Snapshot(*it->first, it->second));
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Aggregation
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6523345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickAggregation::Aggregation()
6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : birth_count_(0) {
6543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickAggregation::~Aggregation() {
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Aggregation::AddDeathSnapshot(const Snapshot& snapshot) {
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddBirth(snapshot.birth());
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  death_threads_[snapshot.death_thread()]++;
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddDeathData(snapshot.death_data());
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Aggregation::AddBirths(const Births& births) {
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddBirth(births);
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_count_ += births.birth_count();
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Aggregation::AddBirth(const BirthOnThread& birth) {
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddBirthPlace(birth.location());
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_threads_[birth.birth_thread()]++;
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Aggregation::AddBirthPlace(const Location& location) {
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  locations_[location]++;
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_files_[location.file_name()]++;
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Aggregation::Write(std::string* output) const {
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (locations_.size() == 1) {
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    locations_.begin()->first.Write(true, true, output);
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
6833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "%" PRIuS " Locations. ", locations_.size());
6843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (birth_files_.size() > 1) {
6853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::StringAppendF(output, "%" PRIuS " Files. ", birth_files_.size());
6863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::StringAppendF(output, "All born in %s. ",
6883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          birth_files_.begin()->first.c_str());
6893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
6923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (birth_threads_.size() > 1) {
6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "%" PRIuS " BirthingThreads. ",
6943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        birth_threads_.size());
6953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "All born on %s. ",
6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        birth_threads_.begin()->first->ThreadName().c_str());
6983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (death_threads_.size() > 1) {
7013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "%" PRIuS " DeathThreads. ",
7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        death_threads_.size());
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
7043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (death_threads_.begin()->first) {
7053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::StringAppendF(output, "All deleted on %s. ",
7063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          death_threads_.begin()->first->ThreadName().c_str());
7073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      output->append("All these objects are still alive.");
7093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (birth_count_ > 1)
7133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "Births=%d ", birth_count_);
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeathData::Write(output);
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Aggregation::Clear() {
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_count_ = 0;
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_files_.clear();
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  locations_.clear();
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  birth_threads_.clear();
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeathData::Clear();
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  death_threads_.clear();
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//------------------------------------------------------------------------------
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Comparison object for sorting.
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottComparator::Comparator()
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : selector_(NIL),
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tiebreaker_(NULL),
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      combined_selectors_(0),
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      use_tiebreaker_for_sort_only_(false) {}
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Comparator::Clear() {
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tiebreaker_) {
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tiebreaker_->Clear();
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete tiebreaker_;
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tiebreaker_ = NULL;
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  use_tiebreaker_for_sort_only_ = false;
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  selector_ = NIL;
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Comparator::operator()(const Snapshot& left,
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            const Snapshot& right) const {
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (selector_) {
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_THREAD:
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.birth_thread() != right.birth_thread() &&
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          left.birth_thread()->ThreadName() !=
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          right.birth_thread()->ThreadName())
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return left.birth_thread()->ThreadName() <
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            right.birth_thread()->ThreadName();
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case DEATH_THREAD:
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.death_thread() != right.death_thread() &&
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          left.DeathThreadName() !=
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          right.DeathThreadName()) {
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (!left.death_thread())
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return true;
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (!right.death_thread())
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return left.DeathThreadName() <
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             right.DeathThreadName();
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_FILE:
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.location().file_name() != right.location().file_name()) {
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int comp = strcmp(left.location().file_name(),
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          right.location().file_name());
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (comp)
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return 0 > comp;
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_FUNCTION:
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.location().function_name() != right.location().function_name()) {
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int comp = strcmp(left.location().function_name(),
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          right.location().function_name());
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (comp)
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return 0 > comp;
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_LINE:
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.location().line_number() != right.location().line_number())
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return left.location().line_number() <
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            right.location().line_number();
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case COUNT:
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.count() != right.count())
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return left.count() > right.count();  // Sort large at front of vector.
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case AVERAGE_DURATION:
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (!left.count() || !right.count())
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.AverageMsDuration() != right.AverageMsDuration())
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return left.AverageMsDuration() > right.AverageMsDuration();
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tiebreaker_)
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return tiebreaker_->operator()(left, right);
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid Comparator::Sort(DataCollector::Collection* collection) const {
81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::sort(collection->begin(), collection->end(), *this);
81672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
81772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Comparator::Equivalent(const Snapshot& left,
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                            const Snapshot& right) const {
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (selector_) {
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_THREAD:
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.birth_thread() != right.birth_thread() &&
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          left.birth_thread()->ThreadName() !=
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              right.birth_thread()->ThreadName())
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case DEATH_THREAD:
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.death_thread() != right.death_thread() &&
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          left.DeathThreadName() != right.DeathThreadName())
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_FILE:
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.location().file_name() != right.location().file_name()) {
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int comp = strcmp(left.location().file_name(),
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          right.location().file_name());
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (comp)
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_FUNCTION:
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.location().function_name() != right.location().function_name()) {
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        int comp = strcmp(left.location().function_name(),
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                          right.location().function_name());
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (comp)
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case COUNT:
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.count() != right.count())
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case AVERAGE_DURATION:
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (left.life_duration() != right.life_duration())
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tiebreaker_ && !use_tiebreaker_for_sort_only_)
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return tiebreaker_->Equivalent(left, right);
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Comparator::Acceptable(const Snapshot& sample) const {
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (required_.size()) {
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    switch (selector_) {
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case BIRTH_THREAD:
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (sample.birth_thread()->ThreadName().find(required_) ==
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            std::string::npos)
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case DEATH_THREAD:
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (sample.DeathThreadName().find(required_) == std::string::npos)
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case BIRTH_FILE:
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (!strstr(sample.location().file_name(), required_.c_str()))
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      case BIRTH_FUNCTION:
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        if (!strstr(sample.location().function_name(), required_.c_str()))
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          return false;
892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      default:
895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        break;
896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tiebreaker_ && !use_tiebreaker_for_sort_only_)
899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return tiebreaker_->Acceptable(sample);
900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Comparator::SetTiebreaker(Selector selector, const std::string& required) {
904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (selector == selector_ || NIL == selector)
905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  combined_selectors_ |= selector;
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (NIL == selector_) {
908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    selector_ = selector;
909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (required.size())
910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      required_ = required;
911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tiebreaker_) {
914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (use_tiebreaker_for_sort_only_) {
915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      Comparator* temp = new Comparator;
916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      temp->tiebreaker_ = tiebreaker_;
917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      tiebreaker_ = temp;
918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tiebreaker_ = new Comparator;
921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!use_tiebreaker_for_sort_only_);
922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  tiebreaker_->SetTiebreaker(selector, required);
924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Comparator::IsGroupedBy(Selector selector) const {
927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return 0 != (selector & combined_selectors_);
928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Comparator::SetSubgroupTiebreaker(Selector selector) {
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (selector == selector_ || NIL == selector)
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!tiebreaker_) {
934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    use_tiebreaker_for_sort_only_ = true;
935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tiebreaker_ = new Comparator;
936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tiebreaker_->SetTiebreaker(selector, "");
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tiebreaker_->SetSubgroupTiebreaker(selector);
939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Comparator::ParseKeyphrase(const std::string& key_phrase) {
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  typedef std::map<const std::string, Selector> KeyMap;
944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static KeyMap key_map;
945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static bool initialized = false;
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!initialized) {
947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    initialized = true;
948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Sorting and aggretation keywords, which specify how to sort the data, or
949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // can specify a required match from the specified field in the record.
950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["count"]    = COUNT;
951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["duration"] = AVERAGE_DURATION;
952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["birth"]    = BIRTH_THREAD;
953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["death"]    = DEATH_THREAD;
954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["file"]     = BIRTH_FILE;
955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["function"] = BIRTH_FUNCTION;
956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["line"]     = BIRTH_LINE;
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Immediate commands that do not involve setting sort order.
959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    key_map["reset"]     = RESET_ALL_DATA;
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string required;
963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Watch for: "sort_key=value" as we parse.
964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  size_t equal_offset = key_phrase.find('=', 0);
965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (key_phrase.npos != equal_offset) {
966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // There is a value that must be matched for the data to display.
967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    required = key_phrase.substr(equal_offset + 1, key_phrase.npos);
968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string keyword(key_phrase.substr(0, equal_offset));
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  keyword = StringToLowerASCII(keyword);
971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  KeyMap::iterator it = key_map.find(keyword);
972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (key_map.end() == it)
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;  // Unknown keyword.
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (it->second == RESET_ALL_DATA)
975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ThreadData::ResetAllThreadData();
976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  else
977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetTiebreaker(key_map[keyword], required);
978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Comparator::ParseQuery(const std::string& query) {
981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Parse each keyphrase between consecutive slashes.
982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < query.size();) {
983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    size_t slash_offset = query.find('/', i);
984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ParseKeyphrase(query.substr(i, slash_offset - i));
985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (query.npos == slash_offset)
986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    i = slash_offset + 1;
988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Select subgroup ordering (if we want to display the subgroup)
991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(COUNT);
992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(AVERAGE_DURATION);
993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(BIRTH_THREAD);
994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(DEATH_THREAD);
995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(BIRTH_FUNCTION);
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(BIRTH_FILE);
997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetSubgroupTiebreaker(BIRTH_LINE);
998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool Comparator::WriteSortGrouping(const Snapshot& sample,
1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                       std::string* output) const {
1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool wrote_data = false;
1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (selector_) {
1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_THREAD:
10073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::StringAppendF(output, "All new on %s ",
10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          sample.birth_thread()->ThreadName().c_str());
1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      wrote_data = true;
1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case DEATH_THREAD:
10133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (sample.death_thread()) {
10143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        base::StringAppendF(output, "All deleted on %s ",
10153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            sample.DeathThreadName().c_str());
10163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      } else {
1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        output->append("All still alive ");
10183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      }
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      wrote_data = true;
1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_FILE:
10233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::StringAppendF(output, "All born in %s ",
10243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          sample.location().file_name());
1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case BIRTH_FUNCTION:
1028c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      output->append("All born in ");
1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sample.location().WriteFunctionName(output);
1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      output->push_back(' ');
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    default:
1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tiebreaker_ && !use_tiebreaker_for_sort_only_) {
1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    wrote_data |= tiebreaker_->WriteSortGrouping(sample, output);
1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return wrote_data;
1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Comparator::WriteSnapshot(const Snapshot& sample,
1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                               std::string* output) const {
1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  sample.death_data().Write(output);
1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(combined_selectors_ & BIRTH_THREAD) ||
1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      !(combined_selectors_ & DEATH_THREAD))
10473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    base::StringAppendF(output, "%s->%s ",
10483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        (combined_selectors_ & BIRTH_THREAD) ? "*" :
10493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          sample.birth().birth_thread()->ThreadName().c_str(),
10503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                        (combined_selectors_ & DEATH_THREAD) ? "*" :
10513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          sample.DeathThreadName().c_str());
1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  sample.birth().location().Write(!(combined_selectors_ & BIRTH_FILE),
1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  !(combined_selectors_ & BIRTH_FUNCTION),
1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  output);
1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace tracked_objects
1058