LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - tracked_objects.h (source / functions) Found Hit Coverage
Test: app.info Lines: 26 0 0.0 %
Date: 2012-06-02 Functions: 27 0 0.0 %

       1                 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       2                 : // Use of this source code is governed by a BSD-style license that can be
       3                 : // found in the LICENSE file.
       4                 : 
       5                 : #ifndef BASE_TRACKED_OBJECTS_H_
       6                 : #define BASE_TRACKED_OBJECTS_H_
       7                 : 
       8                 : //------------------------------------------------------------------------------
       9                 : #include <map>
      10                 : #include <string>
      11                 : #include <vector>
      12                 : 
      13                 : #include "base/lock.h"
      14                 : #include "base/message_loop.h"
      15                 : #include "base/thread_local_storage.h"
      16                 : #include "base/tracked.h"
      17                 : 
      18                 : 
      19                 : namespace tracked_objects {
      20                 : 
      21                 : //------------------------------------------------------------------------------
      22                 : // For a specific thread, and a specific birth place, the collection of all
      23                 : // death info (with tallies for each death thread, to prevent access conflicts).
      24                 : class ThreadData;
      25                 : class BirthOnThread {
      26                 :  public:
      27                 :   explicit BirthOnThread(const Location& location);
      28                 : 
      29               0 :   const Location location() const { return location_; }
      30               0 :   const ThreadData* birth_thread() const { return birth_thread_; }
      31                 : 
      32                 :  private:
      33                 :   // File/lineno of birth.  This defines the essence of the type, as the context
      34                 :   // of the birth (construction) often tell what the item is for.  This field
      35                 :   // is const, and hence safe to access from any thread.
      36                 :   const Location location_;
      37                 : 
      38                 :   // The thread that records births into this object.  Only this thread is
      39                 :   // allowed to access birth_count_ (which changes over time).
      40                 :   const ThreadData* birth_thread_;  // The thread this birth took place on.
      41                 : 
      42                 :   DISALLOW_COPY_AND_ASSIGN(BirthOnThread);
      43                 : };
      44                 : 
      45                 : //------------------------------------------------------------------------------
      46                 : // A class for accumulating counts of births (without bothering with a map<>).
      47                 : 
      48                 : class Births: public BirthOnThread {
      49                 :  public:
      50                 :   explicit Births(const Location& location);
      51                 : 
      52               0 :   int birth_count() const { return birth_count_; }
      53                 : 
      54                 :   // When we have a birth we update the count for this BirhPLace.
      55               0 :   void RecordBirth() { ++birth_count_; }
      56                 : 
      57                 :   // When a birthplace is changed (updated), we need to decrement the counter
      58                 :   // for the old instance.
      59               0 :   void ForgetBirth() { --birth_count_; }  // We corrected a birth place.
      60                 : 
      61                 :  private:
      62                 :   // The number of births on this thread for our location_.
      63                 :   int birth_count_;
      64                 : 
      65                 :   DISALLOW_COPY_AND_ASSIGN(Births);
      66                 : };
      67                 : 
      68                 : //------------------------------------------------------------------------------
      69                 : // Basic info summarizing multiple destructions of an object with a single
      70                 : // birthplace (fixed Location).  Used both on specific threads, and also used
      71                 : // in snapshots when integrating assembled data.
      72                 : 
      73               0 : class DeathData {
      74                 :  public:
      75                 :   // Default initializer.
      76               0 :   DeathData() : count_(0), square_duration_(0) {}
      77                 : 
      78                 :   // When deaths have not yet taken place, and we gather data from all the
      79                 :   // threads, we create DeathData stats that tally the number of births without
      80                 :   // a corrosponding death.
      81               0 :   explicit DeathData(int count) : count_(count), square_duration_(0) {}
      82                 : 
      83                 :   void RecordDeath(const base::TimeDelta& duration);
      84                 : 
      85                 :   // Metrics accessors.
      86               0 :   int count() const { return count_; }
      87               0 :   base::TimeDelta life_duration() const { return life_duration_; }
      88                 :   int64 square_duration() const { return square_duration_; }
      89                 :   int AverageMsDuration() const;
      90                 :   double StandardDeviation() const;
      91                 : 
      92                 :   // Accumulate metrics from other into this.
      93                 :   void AddDeathData(const DeathData& other);
      94                 : 
      95                 :   // Simple print of internal state.
      96                 :   void Write(std::string* output) const;
      97                 : 
      98                 :   void Clear();
      99                 : 
     100                 :  private:
     101                 :   int count_;                // Number of destructions.
     102                 :   base::TimeDelta life_duration_;    // Sum of all lifetime durations.
     103                 :   int64 square_duration_;  // Sum of squares in milliseconds.
     104                 : };
     105                 : 
     106                 : //------------------------------------------------------------------------------
     107                 : // A temporary collection of data that can be sorted and summarized.  It is
     108                 : // gathered (carefully) from many threads.  Instances are held in arrays and
     109                 : // processed, filtered, and rendered.
     110                 : // The source of this data was collected on many threads, and is asynchronously
     111                 : // changing.  The data in this instance is not asynchronously changing.
     112                 : 
     113               0 : class Snapshot {
     114                 :  public:
     115                 :   // When snapshotting a full life cycle set (birth-to-death), use this:
     116                 :   Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread,
     117                 :            const DeathData& death_data);
     118                 : 
     119                 :   // When snapshotting a birth, with no death yet, use this:
     120                 :   Snapshot(const BirthOnThread& birth_on_thread, int count);
     121                 : 
     122                 : 
     123               0 :   const ThreadData* birth_thread() const { return birth_->birth_thread(); }
     124               0 :   const Location location() const { return birth_->location(); }
     125               0 :   const BirthOnThread& birth() const { return *birth_; }
     126               0 :   const ThreadData* death_thread() const {return death_thread_; }
     127               0 :   const DeathData& death_data() const { return death_data_; }
     128                 :   const std::string DeathThreadName() const;
     129                 : 
     130               0 :   int count() const { return death_data_.count(); }
     131               0 :   base::TimeDelta life_duration() const { return death_data_.life_duration(); }
     132                 :   int64 square_duration() const { return death_data_.square_duration(); }
     133               0 :   int AverageMsDuration() const { return death_data_.AverageMsDuration(); }
     134                 : 
     135                 :   void Write(std::string* output) const;
     136                 : 
     137                 :   void Add(const Snapshot& other);
     138                 : 
     139                 :  private:
     140                 :   const BirthOnThread* birth_;  // Includes Location and birth_thread.
     141                 :   const ThreadData* death_thread_;
     142                 :   DeathData death_data_;
     143                 : };
     144                 : //------------------------------------------------------------------------------
     145                 : // DataCollector is a container class for Snapshot and BirthOnThread count
     146                 : // items.  It protects the gathering under locks, so that it could be called via
     147                 : // Posttask on any threads, such as all the target threads in parallel.
     148                 : 
     149               0 : class DataCollector {
     150                 :  public:
     151                 :   typedef std::vector<Snapshot> Collection;
     152                 : 
     153                 :   // Construct with a list of how many threads should contribute.  This helps us
     154                 :   // determine (in the async case) when we are done with all contributions.
     155                 :   DataCollector();
     156                 : 
     157                 :   // Add all stats from the indicated thread into our arrays.  This function is
     158                 :   // mutex protected, and *could* be called from any threads (although current
     159                 :   // implementation serialized calls to Append).
     160                 :   void Append(const ThreadData& thread_data);
     161                 : 
     162                 :   // After the accumulation phase, the following access is to process data.
     163                 :   Collection* collection();
     164                 : 
     165                 :   // After collection of death data is complete, we can add entries for all the
     166                 :   // remaining living objects.
     167                 :   void AddListOfLivingObjects();
     168                 : 
     169                 :  private:
     170                 :   // This instance may be provided to several threads to contribute data.  The
     171                 :   // following counter tracks how many more threads will contribute.  When it is
     172                 :   // zero, then all asynchronous contributions are complete, and locked access
     173                 :   // is no longer needed.
     174                 :   int count_of_contributing_threads_;
     175                 : 
     176                 :   // The array that we collect data into.
     177                 :   Collection collection_;
     178                 : 
     179                 :   // The total number of births recorded at each location for which we have not
     180                 :   // seen a death count.
     181                 :   typedef std::map<const BirthOnThread*, int> BirthCount;
     182                 :   BirthCount global_birth_count_;
     183                 : 
     184                 :   Lock accumulation_lock_;  // Protects access during accumulation phase.
     185                 : 
     186                 :   DISALLOW_COPY_AND_ASSIGN(DataCollector);
     187                 : };
     188                 : 
     189                 : //------------------------------------------------------------------------------
     190                 : // Aggregation contains summaries (totals and subtotals) of groups of Snapshot
     191                 : // instances to provide printing of these collections on a single line.
     192                 : 
     193               0 : class Aggregation: public DeathData {
     194                 :  public:
     195               0 :   Aggregation() : birth_count_(0) {}
     196                 : 
     197                 :   void AddDeathSnapshot(const Snapshot& snapshot);
     198                 :   void AddBirths(const Births& births);
     199                 :   void AddBirth(const BirthOnThread& birth);
     200                 :   void AddBirthPlace(const Location& location);
     201                 :   void Write(std::string* output) const;
     202                 :   void Clear();
     203                 : 
     204                 :  private:
     205                 :   int birth_count_;
     206                 :   std::map<std::string, int> birth_files_;
     207                 :   std::map<Location, int> locations_;
     208                 :   std::map<const ThreadData*, int> birth_threads_;
     209                 :   DeathData death_data_;
     210                 :   std::map<const ThreadData*, int> death_threads_;
     211                 : 
     212                 :   DISALLOW_COPY_AND_ASSIGN(Aggregation);
     213                 : };
     214                 : 
     215                 : //------------------------------------------------------------------------------
     216                 : // Comparator does the comparison of Snapshot instances.  It is
     217                 : // used to order the instances in a vector.  It orders them into groups (for
     218                 : // aggregation), and can also order instances within the groups (for detailed
     219                 : // rendering of the instances).
     220                 : 
     221               0 : class Comparator {
     222                 :  public:
     223                 :   enum Selector {
     224                 :     NIL = 0,
     225                 :     BIRTH_THREAD = 1,
     226                 :     DEATH_THREAD = 2,
     227                 :     BIRTH_FILE = 4,
     228                 :     BIRTH_FUNCTION = 8,
     229                 :     BIRTH_LINE = 16,
     230                 :     COUNT = 32,
     231                 :     AVERAGE_DURATION = 64,
     232                 :     TOTAL_DURATION = 128
     233                 :   };
     234                 : 
     235                 :   explicit Comparator();
     236                 : 
     237                 :   // Reset the comparator to a NIL selector.  Reset() and recursively delete any
     238                 :   // tiebreaker_ entries.  NOTE: We can't use a standard destructor, because
     239                 :   // the sort algorithm makes copies of this object, and then deletes them,
     240                 :   // which would cause problems (either we'd make expensive deep copies, or we'd
     241                 :   // do more thna one delete on a tiebreaker_.
     242                 :   void Clear();
     243                 : 
     244                 :   // The less() operator for sorting the array via std::sort().
     245                 :   bool operator()(const Snapshot& left, const Snapshot& right) const;
     246                 : 
     247                 :   void Sort(DataCollector::Collection* collection) const;
     248                 : 
     249                 :   // Check to see if the items are sort equivalents (should be aggregated).
     250                 :   bool Equivalent(const Snapshot& left, const Snapshot& right) const;
     251                 : 
     252                 :   // Check to see if all required fields are present in the given sample.
     253                 :   bool Acceptable(const Snapshot& sample) const;
     254                 : 
     255                 :   // A comparator can be refined by specifying what to do if the selected basis
     256                 :   // for comparison is insufficient to establish an ordering.  This call adds
     257                 :   // the indicated attribute as the new "least significant" basis of comparison.
     258                 :   void SetTiebreaker(Selector selector, const std::string required);
     259                 : 
     260                 :   // Indicate if this instance is set up to sort by the given Selector, thereby
     261                 :   // putting that information in the SortGrouping, so it is not needed in each
     262                 :   // printed line.
     263                 :   bool IsGroupedBy(Selector selector) const;
     264                 : 
     265                 :   // Using the tiebreakers as set above, we mostly get an ordering, which
     266                 :   // equivalent groups.  If those groups are displayed (rather than just being
     267                 :   // aggregated, then the following is used to order them (within the group).
     268                 :   void SetSubgroupTiebreaker(Selector selector);
     269                 : 
     270                 :   // Translate a keyword and restriction in URL path to a selector for sorting.
     271                 :   void ParseKeyphrase(const std::string key_phrase);
     272                 : 
     273                 :   // Parse a query in an about:objects URL to decide on sort ordering.
     274                 :   bool ParseQuery(const std::string query);
     275                 : 
     276                 :   // Output a header line that can be used to indicated what items will be
     277                 :   // collected in the group.  It lists all (potentially) tested attributes and
     278                 :   // their values (in the sample item).
     279                 :   bool WriteSortGrouping(const Snapshot& sample, std::string* output) const;
     280                 : 
     281                 :   // Output a sample, with SortGroup details not displayed.
     282                 :   void WriteSnapshot(const Snapshot& sample, std::string* output) const;
     283                 : 
     284                 :  private:
     285                 :   // The selector directs this instance to compare based on the specified
     286                 :   // members of the tested elements.
     287                 :   enum Selector selector_;
     288                 : 
     289                 :   // For filtering into acceptable and unacceptable snapshot instance, the
     290                 :   // following is required to be a substring of the selector_ field.
     291                 :   std::string required_;
     292                 : 
     293                 :   // If this instance can't decide on an ordering, we can consult a tie-breaker
     294                 :   // which may have a different basis of comparison.
     295                 :   Comparator* tiebreaker_;
     296                 : 
     297                 :   // We or together all the selectors we sort on (not counting sub-group
     298                 :   // selectors), so that we can tell if we've decided to group on any given
     299                 :   // criteria.
     300                 :   int combined_selectors_;
     301                 : 
     302                 :   // Some tiebreakrs are for subgroup ordering, and not for basic ordering (in
     303                 :   // preparation for aggregation).  The subgroup tiebreakers are not consulted
     304                 :   // when deciding if two items are in equivalent groups.  This flag tells us
     305                 :   // to ignore the tiebreaker when doing Equivalent() testing.
     306                 :   bool use_tiebreaker_for_sort_only_;
     307                 : };
     308                 : 
     309                 : 
     310                 : //------------------------------------------------------------------------------
     311                 : // For each thread, we have a ThreadData that stores all tracking info generated
     312                 : // on this thread.  This prevents the need for locking as data accumulates.
     313                 : 
     314               0 : class ThreadData {
     315                 :  public:
     316                 :   typedef std::map<Location, Births*> BirthMap;
     317                 :   typedef std::map<const Births*, DeathData> DeathMap;
     318                 : 
     319                 :   ThreadData();
     320                 : 
     321                 :   // Using Thread Local Store, find the current instance for collecting data.
     322                 :   // If an instance does not exist, construct one (and remember it for use on
     323                 :   // this thread.
     324                 :   // If shutdown has already started, and we don't yet have an instance, then
     325                 :   // return null.
     326                 :   static ThreadData* current();
     327                 : 
     328                 :   // For a given about:objects URL, develop resulting HTML, and append to
     329                 :   // output.
     330                 :   static void WriteHTML(const std::string& query, std::string* output);
     331                 : 
     332                 :   // For a given accumulated array of results, use the comparator to sort and
     333                 :   // subtotal, writing the results to the output.
     334                 :   static void WriteHTMLTotalAndSubtotals(
     335                 :       const DataCollector::Collection& match_array,
     336                 :       const Comparator& comparator, std::string* output);
     337                 : 
     338                 :   // In this thread's data, find a place to record a new birth.
     339                 :   Births* FindLifetime(const Location& location);
     340                 : 
     341                 :   // Find a place to record a death on this thread.
     342                 :   void TallyADeath(const Births& lifetimes, const base::TimeDelta& duration);
     343                 : 
     344                 :   // (Thread safe) Get start of list of instances.
     345                 :   static ThreadData* first();
     346                 :   // Iterate through the null terminated list of instances.
     347               0 :   ThreadData* next() const { return next_; }
     348                 : 
     349                 :   MessageLoop* message_loop() const { return message_loop_; }
     350                 :   const std::string ThreadName() const;
     351                 : 
     352                 :   // Using our lock, make a copy of the specified maps.  These calls may arrive
     353                 :   // from non-local threads.
     354                 :   void SnapshotBirthMap(BirthMap *output) const;
     355                 :   void SnapshotDeathMap(DeathMap *output) const;
     356                 : 
     357                 :   static void RunOnAllThreads(void (*Func)());
     358                 : 
     359                 :   // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN,
     360                 :   // based on argument being true or false respectively.
     361                 :   // IF tracking is not compiled in, this function will return false.
     362                 :   static bool StartTracking(bool status);
     363                 :   static bool IsActive();
     364                 : 
     365                 : #ifdef OS_WIN
     366                 :   // WARNING: ONLY call this function when all MessageLoops are still intact for
     367                 :   // all registered threads.  IF you call it later, you will crash.
     368                 :   // Note: You don't need to call it at all, and you can wait till you are
     369                 :   // single threaded (again) to do the cleanup via
     370                 :   // ShutdownSingleThreadedCleanup().
     371                 :   // Start the teardown (shutdown) process in a multi-thread mode by disabling
     372                 :   // further additions to thread database on all threads.  First it makes a
     373                 :   // local (locked) change to prevent any more threads from registering.  Then
     374                 :   // it Posts a Task to all registered threads to be sure they are aware that no
     375                 :   // more accumulation can take place.
     376                 :   static void ShutdownMultiThreadTracking();
     377                 : #endif
     378                 : 
     379                 :   // WARNING: ONLY call this function when you are running single threaded
     380                 :   // (again) and all message loops and threads have terminated.  Until that
     381                 :   // point some threads may still attempt to write into our data structures.
     382                 :   // Delete recursively all data structures, starting with the list of
     383                 :   // ThreadData instances.
     384                 :   static void ShutdownSingleThreadedCleanup();
     385                 : 
     386                 :  private:
     387                 :   // Current allowable states of the tracking system.  The states always
     388                 :   // proceed towards SHUTDOWN, and never go backwards.
     389                 :   enum Status {
     390                 :     UNINITIALIZED,
     391                 :     ACTIVE,
     392                 :     SHUTDOWN
     393                 :   };
     394                 : 
     395                 :   // A class used to count down which is accessed by several threads.  This is
     396                 :   // used to make sure RunOnAllThreads() actually runs a task on the expected
     397                 :   // count of threads.
     398               0 :   class ThreadSafeDownCounter {
     399                 :    public:
     400                 :     // Constructor sets the count, once and for all.
     401                 :     explicit ThreadSafeDownCounter(size_t count);
     402                 : 
     403                 :     // Decrement the count, and return true if we hit zero.  Also delete this
     404                 :     // instance automatically when we hit zero.
     405                 :     bool LastCaller();
     406                 : 
     407                 :    private:
     408                 :     size_t remaining_count_;
     409                 :     Lock lock_;  // protect access to remaining_count_.
     410                 :   };
     411                 : 
     412                 : #ifdef OS_WIN
     413                 :   // A Task class that runs a static method supplied, and checks to see if this
     414                 :   // is the last tasks instance (on last thread) that will run the method.
     415                 :   // IF this is the last run, then the supplied event is signalled.
     416                 :   class RunTheStatic : public Task {
     417                 :    public:
     418                 :     typedef void (*FunctionPointer)();
     419                 :     RunTheStatic(FunctionPointer function,
     420                 :                  HANDLE completion_handle,
     421                 :                  ThreadSafeDownCounter* counter);
     422                 :     // Run the supplied static method, and optionally set the event.
     423                 :     void Run();
     424                 : 
     425                 :    private:
     426                 :     FunctionPointer function_;
     427                 :     HANDLE completion_handle_;
     428                 :     // Make sure enough tasks are called before completion is signaled.
     429                 :     ThreadSafeDownCounter* counter_;
     430                 : 
     431                 :     DISALLOW_COPY_AND_ASSIGN(RunTheStatic);
     432                 :   };
     433                 : #endif
     434                 : 
     435                 :   // Each registered thread is called to set status_ to SHUTDOWN.
     436                 :   // This is done redundantly on every registered thread because it is not
     437                 :   // protected by a mutex.  Running on all threads guarantees we get the
     438                 :   // notification into the memory cache of all possible threads.
     439                 :   static void ShutdownDisablingFurtherTracking();
     440                 : 
     441                 :   // We use thread local store to identify which ThreadData to interact with.
     442                 :   static TLSSlot tls_index_ ;
     443                 : 
     444                 :   // Link to the most recently created instance (starts a null terminated list).
     445                 :   static ThreadData* first_;
     446                 :   // Protection for access to first_.
     447                 :   static Lock list_lock_;
     448                 : 
     449                 : 
     450                 :   // We set status_ to SHUTDOWN when we shut down the tracking service. This
     451                 :   // setting is redundantly established by all participating
     452                 :   // threads so that we are *guaranteed* (without locking) that all threads
     453                 :   // can "see" the status and avoid additional calls into the  service.
     454                 :   static Status status_;
     455                 : 
     456                 :   // Link to next instance (null terminated list). Used to globally track all
     457                 :   // registered instances (corresponds to all registered threads where we keep
     458                 :   // data).
     459                 :   ThreadData* next_;
     460                 : 
     461                 :   // The message loop where tasks needing to access this instance's private data
     462                 :   // should be directed.  Since some threads have no message loop, some
     463                 :   // instances have data that can't be (safely) modified externally.
     464                 :   MessageLoop* message_loop_;
     465                 : 
     466                 :   // A map used on each thread to keep track of Births on this thread.
     467                 :   // This map should only be accessed on the thread it was constructed on.
     468                 :   // When a snapshot is needed, this structure can be locked in place for the
     469                 :   // duration of the snapshotting activity.
     470                 :   BirthMap birth_map_;
     471                 : 
     472                 :   // Similar to birth_map_, this records informations about death of tracked
     473                 :   // instances (i.e., when a tracked instance was destroyed on this thread).
     474                 :   DeathMap death_map_;
     475                 : 
     476                 :   // Lock to protect *some* access to BirthMap and DeathMap.  We only use
     477                 :   // locking protection when we are growing the maps, or using an iterator.  We
     478                 :   // only do writes to members from this thread, so the updates of values are
     479                 :   // atomic.  Folks can read from other threads, and get (via races) new or old
     480                 :   // data, but that is considered acceptable errors (mis-information).
     481                 :   Lock lock_;
     482                 : 
     483                 :   DISALLOW_COPY_AND_ASSIGN(ThreadData);
     484                 : };
     485                 : 
     486                 : 
     487                 : //------------------------------------------------------------------------------
     488                 : // Provide simple way to to start global tracking, and to tear down tracking
     489                 : // when done.  Note that construction and destruction of this object must be
     490                 : // done when running in single threaded mode (before spawning a lot of threads
     491                 : // for construction, and after shutting down all the threads for destruction).
     492                 : 
     493                 : class AutoTracking {
     494                 :  public:
     495                 :   AutoTracking() { ThreadData::StartTracking(true); }
     496                 : 
     497                 :   ~AutoTracking() {
     498                 : #ifndef NDEBUG  // Don't call these in a Release build: they just waste time.
     499                 :     // The following should ONLY be called when in single threaded mode. It is
     500                 :     // unsafe to do this cleanup if other threads are still active.
     501                 :     // It is also very unnecessary, so I'm only doing this in debug to satisfy
     502                 :     // purify (if we need to!).
     503                 :     ThreadData::ShutdownSingleThreadedCleanup();
     504                 : #endif
     505                 :   }
     506                 : 
     507                 :  private:
     508                 :   DISALLOW_COPY_AND_ASSIGN(AutoTracking);
     509                 : };
     510                 : 
     511                 : 
     512                 : }  // namespace tracked_objects
     513                 : 
     514                 : #endif  // BASE_TRACKED_OBJECTS_H_

Generated by: LCOV version 1.7