15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_TRACKED_OBJECTS_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_TRACKED_OBJECTS_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stack>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h"
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/basictypes.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/profiler/alternate_timer.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/profiler/tracked_time.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_local_storage.h"
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace base {
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)struct TrackingInfo;
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TrackedObjects provides a database of stats about objects (generally Tasks)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that are tracked.  Tracking means their birth, death, duration, birth thread,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// death thread, and birth place are recorded.  This data is carefully spread
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// across a series of objects so that the counts and times can be rapidly
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// updated without (usually) having to lock the data, and hence there is usually
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// very little contention caused by the tracking.  The data can be viewed via
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the about:profiler URL, with a variety of sorting and filtering choices.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These classes serve as the basis of a profiler of sorts for the Tasks system.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As a result, design decisions were made to maximize speed, by minimizing
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recurring allocation/deallocation, lock contention and data copying.  In the
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "stable" state, which is reached relatively quickly, there is no separate
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// marginal allocation cost associated with construction or destruction of
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tracked objects, no locks are generally employed, and probably the largest
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// computational cost is associated with obtaining start and stop times for
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances as they are created and destroyed.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following describes the lifecycle of tracking an instance.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// First off, when the instance is created, the FROM_HERE macro is expanded
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to specify the birth place (file, line, function) where the instance was
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// created.  That data is used to create a transient Location instance
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encapsulating the above triple of information.  The strings (like __FILE__)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are passed around by reference, with the assumption that they are static, and
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will never go away.  This ensures that the strings can be dealt with as atoms
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with great efficiency (i.e., copying of strings is never needed, and
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// comparisons for equality can be based on pointer comparisons).
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Next, a Births instance is created for use ONLY on the thread where this
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance was created.  That Births instance records (in a base class
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BirthOnThread) references to the static data provided in a Location instance,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as a pointer specifying the thread on which the birth takes place.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Hence there is at most one Births instance for each Location on each thread.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The derived Births class contains slots for recording statistics about all
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances born at the same location.  Statistics currently include only the
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// count of instances constructed.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since the base class BirthOnThread contains only constant data, it can be
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freely accessed by any thread at any time (i.e., only the statistic needs to
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be handled carefully, and stats are updated exclusively on the birth thread).
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For Tasks, having now either constructed or found the Births instance
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// described above, a pointer to the Births instance is then recorded into the
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PendingTask structure in MessageLoop.  This fact alone is very useful in
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// debugging, when there is a question of where an instance came from.  In
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// addition, the birth time is also recorded and used to later evaluate the
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lifetime duration of the whole Task.  As a result of the above embedding, we
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can find out a Task's location of birth, and thread of birth, without using
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any locks, as all that data is constant across the life of the process.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The above work *could* also be done for any other object as well by calling
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of memory used in the above data structures depends on how many
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads there are, and how many Locations of construction there are.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fortunately, we don't use memory that is the product of those two counts, but
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather we only need one Births instance for each thread that constructs an
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance at a Location. In many cases, instances are only created on one
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread, so the memory utilization is actually fairly restrained.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Lastly, when an instance is deleted, the final tallies of statistics are
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// carefully accumulated.  That tallying writes into slots (members) in a
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// collection of DeathData instances.  For each birth place Location that is
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destroyed on a thread, there is a DeathData instance to record the additional
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// death count, as well as accumulate the run-time and queue-time durations for
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the instance as it is destroyed (dies).  By maintaining a single place to
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// aggregate this running sum *only* for the given thread, we avoid the need to
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lock such DeathData instances. (i.e., these accumulated stats in a DeathData
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance are exclusively updated by the singular owning thread).
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// With the above lifecycle description complete, the major remaining detail is
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// explaining how each thread maintains a list of DeathData instances, and of
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Births instances, and is able to avoid additional (redundant/unnecessary)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocations.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each thread maintains a list of data items specific to that thread in a
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ThreadData instance (for that specific thread only).  The two critical items
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are lists of DeathData and Births instances.  These lists are maintained in
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// STL maps, which are indexed by Location. As noted earlier, we can compare
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// locations very efficiently as we consider the underlying data (file,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function, line) to be atoms, and hence pointer comparison is used rather than
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (slow) string comparisons.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To provide a mechanism for iterating over all "known threads," which means
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads that have recorded a birth or a death, we create a singly linked list
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of ThreadData instances. Each such instance maintains a pointer to the next
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one.  A static member of ThreadData provides a pointer to the first item on
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this global list, and access via that all_thread_data_list_head_ item
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requires the use of the list_lock_.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When new ThreadData instances is added to the global list, it is pre-pended,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which ensures that any prior acquisition of the list is valid (i.e., the
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// holder can iterate over it without fear of it changing, or the necessity of
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using an additional lock.  Iterations are actually pretty rare (used
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// primarilly for cleanup, or snapshotting data for display), so this lock has
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// very little global performance impact.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The above description tries to define the high performance (run time)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// portions of these classes.  After gathering statistics, calls instigated
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by visiting about:profiler will assemble and aggregate data for display.  The
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// following data structures are used for producing such displays.  They are
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not performance critical, and their only major constraint is that they should
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be able to run concurrently with ongoing augmentation of the birth and death
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This header also exports collection of classes that provide "snapshotted"
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representations of the core tracked_objects:: classes.  These snapshotted
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representations are designed for safe transmission of the tracked_objects::
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data across process boundaries.  Each consists of:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (1) a default constructor, to support the IPC serialization macros,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (2) a constructor that extracts data from the type being snapshotted, and
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (3) the snapshotted data.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For a given birth location, information about births is spread across data
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// structures that are asynchronously changing on various threads.  For
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// serialization and display purposes, we need to construct TaskSnapshot
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances for each combination of birth thread, death thread, and location,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// along with the count of such lifetimes.  We gather such data into a
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TaskSnapshot instances, so that such instances can be sorted and
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// aggregated (and remain frozen during our processing).
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The ProcessDataSnapshot struct is a serialized representation of the list
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of ThreadData objects for a process.  It holds a set of TaskSnapshots
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and tracks parent/child relationships for the executed tasks.  The statistics
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a snapshot are gathered asynhcronously relative to their ongoing updates.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is possible, though highly unlikely, that stats could be incorrectly
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recorded by this process (all data is held in 32 bit ints, but we are not
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// atomically collecting all data, so we could have count that does not, for
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// example, match with the number of durations we accumulated).  The advantage
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to having fast (non-atomic) updates of the data outweighs the minimal risk of
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a singular corrupt statistic snapshot (only the snapshot could be corrupt,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not the underlying and ongoing statistic).  In constrast, pointer data that
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is accessed during snapshotting is completely invariant, and hence is
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// perfectly acquired (i.e., no potential corruption, and no risk of a bad
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory reference).
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): We can implement a Snapshot system that *tries* to grab the
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// snapshots on the source threads *when* they have MessageLoops available
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (worker threads don't have message loops generally, and hence gathering from
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// them will continue to be asynchronous).  We had an implementation of this in
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the past, but the difficulty is dealing with message loops being terminated.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We can *try* to spam the available threads via some message loop proxy to
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// achieve this feat, and it *might* be valuable when we are colecting data for
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// upload via UMA (where correctness of data may be more significant than for a
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// single screen of about:profiler).
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): We should support (optionally) the recording of parent-child
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relationships for tasks.  This should be done by detecting what tasks are
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Born during the running of a parent task.  The resulting data can be used by
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a smarter profiler to aggregate the cost of a series of child tasks into
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ancestor task.  It can also be used to illuminate what child or parent is
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// related to each task.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): We need to store DataCollections, and provide facilities for
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// taking the difference between two gathered DataCollections.  For now, we're
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just adding a hack that Reset()s to zero all counts and stats.  This is also
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// done in a slighly thread-unsafe fashion, as the resetting is done
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// asynchronously relative to ongoing updates (but all data is 32 bit in size).
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For basic profiling, this will work "most of the time," and should be
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sufficient... but storing away DataCollections is the "right way" to do this.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We'll accomplish this via JavaScript storage of snapshots, and then we'll
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// remove the Reset() methods.  We may also need a short-term-max value in
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DeathData that is reset (as synchronously as possible) during each snapshot.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This will facilitate displaying a max value for each snapshot period.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tracked_objects {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For a specific thread, and a specific birth place, the collection of all
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// death info (with tallies for each death thread, to prevent access conflicts).
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadData;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT BirthOnThread {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BirthOnThread(const Location& location, const ThreadData& current);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Location location() const { return location_; }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ThreadData* birth_thread() const { return birth_thread_; }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // File/lineno of birth.  This defines the essence of the task, as the context
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the birth (construction) often tell what the item is for.  This field
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is const, and hence safe to access from any thread.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Location location_;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The thread that records births into this object.  Only this thread is
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allowed to update birth_count_ (which changes over time).
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ThreadData* const birth_thread_;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BirthOnThread);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A "snapshotted" representation of the BirthOnThread class.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT BirthOnThreadSnapshot {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BirthOnThreadSnapshot();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit BirthOnThreadSnapshot(const BirthOnThread& birth);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~BirthOnThreadSnapshot();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LocationSnapshot location;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string thread_name;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class for accumulating counts of births (without bothering with a map<>).
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT Births: public BirthOnThread {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Births(const Location& location, const ThreadData& current);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int birth_count() const;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When we have a birth we update the count for this birthplace.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordBirth();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When a birthplace is changed (updated), we need to decrement the counter
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for the old instance.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ForgetBirth();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hack to quickly reset all counts to zero.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Clear();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of births on this thread for our location_.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int birth_count_;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Births);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic info summarizing multiple destructions of a tracked object with a
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// single birthplace (fixed Location).  Used both on specific threads, and also
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in snapshots when integrating assembled data.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT DeathData {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default initializer.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeathData();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When deaths have not yet taken place, and we gather data from all the
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads, we create DeathData stats that tally the number of births without
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a corresponding death.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DeathData(int count);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update stats for a task destruction (death) that had a Run() time of
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |duration|, and has had a queueing delay of |queue_duration|.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordDeath(const int32 queue_duration,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const int32 run_duration,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   int random_number);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Metrics accessors, used only for serialization and in tests.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count() const;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_sum() const;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_max() const;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_sample() const;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_sum() const;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_max() const;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_sample() const;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the max values to zero.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetMax();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset all tallies to zero. This is used as a hack on realtime data.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Clear();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Members are ordered from most regularly read and updated, to least
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frequently used.  This might help a bit with cache lines.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Number of runs seen (divisor for calculating averages).
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count_;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Basic tallies, used to compute averages.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_sum_;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_sum_;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Max values, used by local visualization routines.  These are often read,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but rarely updated.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_max_;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_max_;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Samples, used by crowd sourcing gatherers.  These are almost never read,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and rarely updated.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_sample_;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_sample_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A "snapshotted" representation of the DeathData class.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT DeathDataSnapshot {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeathDataSnapshot();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DeathDataSnapshot(const DeathData& death_data);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DeathDataSnapshot();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int count;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_sum;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_max;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 run_duration_sample;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_sum;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_max;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 queue_duration_sample;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A temporary collection of data that can be sorted and summarized.  It is
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gathered (carefully) from many threads.  Instances are held in arrays and
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// processed, filtered, and rendered.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The source of this data was collected on many threads, and is asynchronously
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// changing.  The data in this instance is not asynchronously changing.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT TaskSnapshot {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskSnapshot();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TaskSnapshot(const BirthOnThread& birth,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const DeathData& death_data,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const std::string& death_thread_name);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TaskSnapshot();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BirthOnThreadSnapshot birth;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeathDataSnapshot death_data;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string death_thread_name;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For each thread, we have a ThreadData that stores all tracking info generated
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on this thread.  This prevents the need for locking as data accumulates.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use ThreadLocalStorage to quickly identfy the current ThreadData context.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We also have a linked list of ThreadData instances, and that list is used to
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// harvest data from all existing instances.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ProcessDataSnapshot;
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass BASE_EXPORT TaskStopwatch;
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT ThreadData {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Current allowable states of the tracking system.  The states can vary
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Status {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UNINITIALIZED,              // PRistine, link-time state before running.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DORMANT_DURING_TESTS,       // Only used during testing.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DEACTIVATED,                // No longer recording profling.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PROFILING_ACTIVE,           // Recording profiles (no parent-child links).
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PROFILING_CHILDREN_ACTIVE,  // Fully active, recording parent-child links.
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STATUS_LAST = PROFILING_CHILDREN_ACTIVE
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<Location, Births*> BirthMap;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<const Births*, DeathData> DeathMap;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::pair<const Births*, const Births*> ParentChildPair;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::set<ParentChildPair> ParentChildSet;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::stack<const Births*> ParentStack;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the current thread context with a new instance of ThreadData.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is used by all threads that have names, and should be explicitly
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set *before* any births on the threads have taken place.  It is generally
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only used by the message loop, which has a well defined thread name.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void InitializeThreadContext(const std::string& suggested_name);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using Thread Local Store, find the current instance for collecting data.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If an instance does not exist, construct one (and remember it for use on
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this thread.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This may return NULL if the system is disabled for any reason.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadData* Get();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fills |process_data| with all the recursive results in our process.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // During the scavenging, if |reset_max| is true, then the DeathData instances
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // max-values are reset to zero during this scan.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Snapshot(bool reset_max, ProcessDataSnapshot* process_data);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finds (or creates) a place to count births from the given location in this
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread, and increment that tally.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TallyABirthIfActive will returns NULL if the birth cannot be tallied.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Births* TallyABirthIfActive(const Location& location);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records the end of a timed run of an object.  The |completed_task| contains
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a pointer to a Births, the time_posted, and a delayed_start_time if any.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The |start_of_run| indicates when we started to perform the run of the
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // task.  The delayed_start_time is non-null for tasks that were posted as
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delayed tasks, and it indicates when the task should have run (i.e., when
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it should have posted out of the timer queue, and into the work queue.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The |end_of_run| was just obtained by a call to Now() (just after the task
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finished). It is provided as an argument to help with testing.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void TallyRunOnNamedThreadIfTracking(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::TrackingInfo& completed_task,
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const TaskStopwatch& stopwatch);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the end of a timed run of an object.  The |birth| is the record for
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the instance, the |time_posted| records that instant, which is presumed to
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be when the task was posted into a queue to run on a worker thread.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The |start_of_run| is when the worker thread started to perform the run of
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the task.
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The |end_of_run| was just obtained by a call to Now() (just after the task
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finished).
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void TallyRunOnWorkerThreadIfTracking(
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Births* birth,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const TrackedTime& time_posted,
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const TaskStopwatch& stopwatch);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record the end of execution in region, generally corresponding to a scope
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // being exited.
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void TallyRunInAScopedRegionIfTracking(
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Births* birth,
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const TaskStopwatch& stopwatch);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& thread_name() const { return thread_name_; }
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hack: asynchronously clear all birth counts and death tallies data values
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in all ThreadData instances.  The numerical (zeroing) part is done without
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use of a locks or atomics exchanges, and may (for int64 values) produce
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bogus counts VERY rarely.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void ResetAllThreadData();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes all statics if needed (this initialization call should be made
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // while we are single threaded). Returns false if unable to initialize.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool Initialize();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets internal status_.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |status| is false, then status_ is set to DEACTIVATED.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PROFILING_CHILDREN_ACTIVE.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If tracking is not compiled in, this function will return false.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If parent-child tracking is not compiled in, then an attempt to set the
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // status to PROFILING_CHILDREN_ACTIVE will only result in a status of
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PROFILING_ACTIVE (i.e., it can't be set to a higher level than what is
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compiled into the binary, and parent-child tracking at the
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PROFILING_CHILDREN_ACTIVE level might not be compiled in).
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool InitializeAndSetTrackingStatus(Status status);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Status status();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicate if any sort of profiling is being done (i.e., we are more than
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DEACTIVATED).
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool TrackingStatus();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For testing only, indicate if the status of parent-child tracking is turned
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on.  This is currently a compiled option, atop TrackingStatus().
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool TrackingParentChildStatus();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Marks a start of a tracked run. It's super fast when tracking is disabled,
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and has some internal side effects when we are tracking, so that we can
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // deduce the amount of time accumulated outside of execution of tracked runs.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The task that will be tracked is passed in as |parent| so that parent-child
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // relationships can be (optionally) calculated.
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static void PrepareForStartOfRun(const Births* parent);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Provide a time function that does nothing (runs fast) when we don't have
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the profiler enabled.  It will generally be optimized away when it is
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the code).
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static TrackedTime Now();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the function |now| to provide current times, instead of calling the
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TrackedTime::Now() function.  Since this alternate function is being used,
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the other time arguments (used for calculating queueing delay) will be
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ignored.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SetAlternateTimeSource(NowFunction* now);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function can be called at process termination to validate that thread
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cleanup routines have been called for at least some number of named
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void EnsureCleanupWasCalled(int major_threads_shutdown_count);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  friend class TaskStopwatch;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow only tests to call ShutdownSingleThreadedCleanup.  We NEVER call it
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in production code.
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // better change of optimizing (inlining? etc.) private methods (knowing that
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there will be no need for an external entry point).
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class TrackedObjectsTest;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<const BirthOnThread*, int> BirthCountMap;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Worker thread construction creates a name since there is none.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ThreadData(int thread_number);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Message loop based construction should provide a name.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ThreadData(const std::string& suggested_name);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ThreadData();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Push this instance to the head of all_thread_data_list_head_, linking it to
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the previous head.  This is performed after each construction, and leaves
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the instance permanently on that list.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PushToHeadOfList();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (Thread safe) Get start of list of all ThreadData instances using the lock.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadData* first();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Iterate through the null terminated list of ThreadData instances.
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadData* next() const;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In this thread's data, record a new birth.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Births* TallyABirth(const Location& location);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find a place to record a death on this thread.
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void TallyADeath(const Births& birth,
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   int32 queue_duration,
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   const TaskStopwatch& stopwatch);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Snapshot (under a lock) the profiled data for the tasks in each ThreadData
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance.  Also updates the |birth_counts| tally for each task to keep
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // track of the number of living instances of the task.  If |reset_max| is
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true, then the max values in each DeathData instance are reset during the
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scan.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SnapshotAllExecutedTasks(bool reset_max,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ProcessDataSnapshot* process_data,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       BirthCountMap* birth_counts);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Snapshots (under a lock) the profiled data for the tasks for this thread
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and writes all of the executed tasks' data -- i.e. the data for the tasks
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with with entries in the death_map_ -- into |process_data|.  Also updates
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the |birth_counts| tally for each task to keep track of the number of
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // living instances of the task -- that is, each task maps to the number of
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // births for the task that have not yet been balanced by a death.  If
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |reset_max| is true, then the max values in each DeathData instance are
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reset during the scan.
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SnapshotExecutedTasks(bool reset_max,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProcessDataSnapshot* process_data,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             BirthCountMap* birth_counts);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using our lock, make a copy of the specified maps.  This call may be made
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on  non-local threads, which necessitate the use of the lock to prevent
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the map(s) from being reallocaed while they are copied. If |reset_max| is
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true, then, just after we copy the DeathMap, we will set the max values to
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // zero in the active DeathMap (not the snapshot).
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SnapshotMaps(bool reset_max,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    BirthMap* birth_map,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    DeathMap* death_map,
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ParentChildSet* parent_child_set);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Using our lock to protect the iteration, Clear all birth and death data.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method is called by the TLS system when a thread terminates.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The argument may be NULL if this thread has never tracked a birth or death.
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void OnThreadTermination(void* thread_data);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method should be called when a worker thread terminates, so that we
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can save all the thread data into a cache of reusable ThreadData instances.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnThreadTerminationCleanup();
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cleans up data structures, and returns statics to near pristine (mostly
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // uninitialized) state.  If there is any chance that other threads are still
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using the data structures, then the |leak| argument should be passed in as
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true, and the data structures (birth maps, death maps, ThreadData
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // insntances, etc.) will be leaked and not deleted.  If you have joined all
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads since the time that InitializeAndSetTrackingStatus() was called,
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // then you can pass in a |leak| value of false, and this function will
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delete recursively all data structures, starting with the list of
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ThreadData instances.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void ShutdownSingleThreadedCleanup(bool leak);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When non-null, this specifies an external function that supplies monotone
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // increasing time functcion.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static NowFunction* now_function_;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If true, now_function_ returns values that can be used to calculate queue
5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // time.
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static bool now_function_is_time_;
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use thread local store to identify which ThreadData to interact with.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static base::ThreadLocalStorage::StaticSlot tls_index_;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // List of ThreadData instances for use with worker threads. When a worker
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread is done (terminated), we push it onto this llist.  When a new worker
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread is created, we first try to re-use a ThreadData instance from the
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // list, and if none are available, construct a new one.
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is only accessed while list_lock_ is held.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadData* first_retired_worker_;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Link to the most recently created instance (starts a null terminated list).
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The list is traversed by about:profiler when it needs to snapshot data.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is only accessed while list_lock_ is held.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ThreadData* all_thread_data_list_head_;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The next available worker thread number.  This should only be accessed when
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the list_lock_ is held.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int worker_thread_data_creation_count_;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of times TLS has called us back to cleanup a ThreadData
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance. This is only accessed while list_lock_ is held.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int cleanup_count_;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Incarnation sequence number, indicating how many times (during unittests)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we've either transitioned out of UNINITIALIZED, or into that state.  This
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value is only accessed while the list_lock_ is held.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int incarnation_counter_;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protection for access to all_thread_data_list_head_, and to
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unregistered_thread_data_pool_.  This lock is leaked at shutdown.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The lock is very infrequently used, so we can afford to just make a lazy
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance and be safe.
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static base::LazyInstance<base::Lock>::Leaky list_lock_;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We set status_ to SHUTDOWN when we shut down the tracking service.
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Status status_;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Link to next instance (null terminated list). Used to globally track all
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // registered instances (corresponds to all registered threads where we keep
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // data).
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadData* next_;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pointer to another ThreadData instance for a Worker-Thread that has been
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // retired (its thread was terminated).  This value is non-NULL only for a
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // retired ThreadData associated with a Worker-Thread.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadData* next_retired_worker_;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The name of the thread that is being recorded.  If this thread has no
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message_loop, then this is a worker thread, with a sequence number postfix.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string thread_name_;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicate if this is a worker thread, and the ThreadData contexts should be
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stored in the unregistered_thread_data_pool_ when not in use.
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Value is zero when it is not a worker thread.  Value is a positive integer
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // corresponding to the created thread name if it is a worker thread.
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int worker_thread_number_;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A map used on each thread to keep track of Births on this thread.
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This map should only be accessed on the thread it was constructed on.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When a snapshot is needed, this structure can be locked in place for the
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // duration of the snapshotting activity.
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BirthMap birth_map_;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Similar to birth_map_, this records informations about death of tracked
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instances (i.e., when a tracked instance was destroyed on this thread).
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is locked before changing, and hence other threads may access it by
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // locking before reading it.
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeathMap death_map_;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A set of parents that created children tasks on this thread. Each pair
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // corresponds to potentially non-local Births (location and thread), and a
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // local Births (that took place on this thread).
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParentChildSet parent_child_set_;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Lock to protect *some* access to BirthMap and DeathMap.  The maps are
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // regularly read and written on this thread, but may only be read from other
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads.  To support this, we acquire this lock if we are writing from this
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread, or reading from another thread.  For reading from this thread we
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't need a lock, as there is no potential for a conflict since the
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // writing is only done from this thread.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock map_lock_;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The stack of parents that are currently being profiled. This includes only
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // tasks that have started a timer recently via PrepareForStartOfRun(), but
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // not yet concluded with a NowForEndOfRun().  Usually this stack is one deep,
6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // but if a scoped region is profiled, or <sigh> a task runs a nested-message
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // loop, then the stack can grow larger.  Note that we don't try to deduct
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // time in nested porfiles, as our current timer is based on wall-clock time,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and not CPU time (and we're hopeful that nested timing won't be a
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // significant additional cost).
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParentStack parent_stack_;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A random number that we used to select decide which sample to keep as a
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // representative sample in each DeathData instance.  We can't start off with
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // much randomness (because we can't call RandInt() on all our threads), so
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we stir in more and more as we go.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 random_number_;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record of what the incarnation_counter_ was when this instance was created.
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the incarnation_counter_ has changed, then we avoid pushing into the
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pool (this is only critical in tests which go through multiple
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // incarnations).
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int incarnation_count_for_pool_;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Most recently started (i.e. most nested) stopwatch on the current thread,
6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // if it exists; NULL otherwise.
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TaskStopwatch* current_stopwatch_;
6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ThreadData);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Stopwatch to measure task run time or simply create a time interval that will
7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// be subtracted from the current most nested task's run time. Stopwatches
7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// coordinate with the stopwatches in which they are nested to avoid
7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// double-counting nested tasks run times.
7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass BASE_EXPORT TaskStopwatch {
7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Starts the stopwatch.
7091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TaskStopwatch();
7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ~TaskStopwatch();
7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Stops stopwatch.
7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void Stop();
7141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns the start time.
7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TrackedTime StartTime() const;
7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Task's duration is calculated as the wallclock duration between starting
7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // and stopping this stopwatch, minus the wallclock durations of any other
7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // instances that are immediately nested in this one, started and stopped on
7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // this thread during that period.
7221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int32 RunDurationMs() const;
7231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns tracking info for the current thread.
7251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ThreadData* GetThreadData() const;
7261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Time when the stopwatch was started.
7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TrackedTime start_time_;
7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Wallclock duration of the task.
7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int32 wallclock_duration_ms_;
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Tracking info for the current thread.
7351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ThreadData* current_thread_data_;
7361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Sum of wallclock durations of all stopwatches that were directly nested in
7381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // this one.
7391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int32 excluded_duration_ms_;
7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Stopwatch which was running on our thread when this stopwatch was started.
7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // That preexisting stopwatch must be adjusted to the exclude the wallclock
7431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // duration of this stopwatch.
7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TaskStopwatch* parent_;
7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if DCHECK_IS_ON
7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // State of the stopwatch. Stopwatch is first constructed in a running state,
7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // then stopped, then destructed.
7491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  enum {
7501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    RUNNING,
7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    STOPPED
7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } state_;
7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Currently running stopwatch that is directly nested in this one, if such
7551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // stopwatch exists. NULL otherwise.
7561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TaskStopwatch* child_;
7571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
7581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
7591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//------------------------------------------------------------------------------
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A snapshotted representation of a (parent, child) task pair, for tracking
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hierarchical profiles.
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT ParentChildPairSnapshot {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParentChildPairSnapshot();
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ParentChildPairSnapshot(
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ThreadData::ParentChildPair& parent_child);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ParentChildPairSnapshot();
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BirthOnThreadSnapshot parent;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BirthOnThreadSnapshot child;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A snapshotted representation of the list of ThreadData objects for a process.
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT ProcessDataSnapshot {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessDataSnapshot();
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ProcessDataSnapshot();
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<TaskSnapshot> tasks;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<ParentChildPairSnapshot> descendants;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int process_id;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace tracked_objects
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_TRACKED_OBJECTS_H_
791