Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_TRACKED_OBJECTS_H_ | 5 #ifndef BASE_TRACKED_OBJECTS_H_ |
| 6 #define BASE_TRACKED_OBJECTS_H_ | 6 #define BASE_TRACKED_OBJECTS_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <stack> | 10 #include <stack> |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 // purposes, we need to construct Snapshot instances for each combination of | 130 // purposes, we need to construct Snapshot instances for each combination of |
| 131 // birth thread, death thread, and location, along with the count of such | 131 // birth thread, death thread, and location, along with the count of such |
| 132 // lifetimes. We gather such data into a Snapshot instances, so that such | 132 // lifetimes. We gather such data into a Snapshot instances, so that such |
| 133 // instances can be sorted and aggregated (and remain frozen during our | 133 // instances can be sorted and aggregated (and remain frozen during our |
| 134 // processing). Snapshot instances use pointers to constant portions of the | 134 // processing). Snapshot instances use pointers to constant portions of the |
| 135 // birth and death datastructures, but have local (frozen) copies of the actual | 135 // birth and death datastructures, but have local (frozen) copies of the actual |
| 136 // statistics (birth count, durations, etc. etc.). | 136 // statistics (birth count, durations, etc. etc.). |
| 137 // | 137 // |
| 138 // A DataCollector is a container object that holds a set of Snapshots. The | 138 // A DataCollector is a container object that holds a set of Snapshots. The |
| 139 // statistics in a snapshot are gathered asynhcronously relative to their | 139 // statistics in a snapshot are gathered asynhcronously relative to their |
| 140 // ongoing updates. It is possible, though highly unlikely, that stats such | 140 // ongoing updates. It is possible, though highly unlikely, that stats could be |
| 141 // as a 64bit counter could be incorrectly recorded by this process. The | 141 // incorrectly recorded by this process (all data is held in 32 bit ints, but we |
| 142 // are not atomically collecting all data, so we could have count that does not, | |
| 143 // for example, match with the number of durations we accumulated). The | |
| 142 // advantage to having fast (non-atomic) updates of the data outweighs the | 144 // advantage to having fast (non-atomic) updates of the data outweighs the |
| 143 // minimal risk of a singular corrupt statistic snapshot (only the snapshot | 145 // minimal risk of a singular corrupt statistic snapshot (only the snapshot |
| 144 // could be corrupt, not the underlying and ongoing statistic). In constrast, | 146 // could be corrupt, not the underlying and ongoing statistic). In constrast, |
| 145 // pointer data that is accessed during snapshotting is completely invariant, | 147 // pointer data that is accessed during snapshotting is completely invariant, |
| 146 // and hence is perfectly acquired (i.e., no potential corruption, and no risk | 148 // and hence is perfectly acquired (i.e., no potential corruption, and no risk |
| 147 // of a bad memory reference). | 149 // of a bad memory reference). |
| 148 // | 150 // |
| 149 // After an array of Snapshots instances are collected into a DataCollector, | 151 // After an array of Snapshots instances are collected into a DataCollector, |
| 150 // they need to be prepared for displaying our output. We currently implement a | 152 // they need to be prepared for displaying our output. We currently implement a |
| 151 // direct rendering to HTML, but we will soon have a JSON serialization as well. | 153 // serialization into a Value hierarchy, which is automatically translated to |
| 152 | 154 // JSON when supplied to rendering Java Scirpt. |
| 153 // For direct HTML display, the data must be sorted, and possibly aggregated | |
| 154 // (example: how many threads are in a specific consecutive set of Snapshots? | |
| 155 // What was the total birth count for that set? etc.). Aggregation instances | |
| 156 // collect running sums of any set of snapshot instances, and are used to print | |
| 157 // sub-totals in an about:profiler page. | |
| 158 // | 155 // |
| 159 // TODO(jar): I need to store DataCollections, and provide facilities for taking | 156 // TODO(jar): We can implement a Snapshot system that *tries* to grab the |
| 160 // the difference between two gathered DataCollections. For now, I'm just | 157 // snapshots on the source threads *when* they have MessageLoops available |
| 161 // adding a hack that Reset()s to zero all counts and stats. This is also | 158 // (worker threads don't have message loops generally, and hence gathering from |
| 159 // them will continue to be asynchronous). We had an implementation of this in | |
| 160 // the past, but the difficulty is dealing with message loops being terminated. | |
| 161 // We can *try* to spam the available threads via some message loop proxy to | |
| 162 // achieve this feat, and it *might* be valuable when we are colecting data for | |
| 163 // upload via UMA (where correctness of data may be more significant than for a | |
| 164 // single screen of about:profiler). | |
| 165 // | |
| 166 // TODO(jar): We need to save a single sample in each DeathData instance of the | |
| 167 // times recorded. This sample should be selected in a uniformly random way. | |
| 168 // | |
| 169 // TODO(jar): We should support (optionally) the recording of of parent-child | |
|
ramant (doing other things)
2011/11/18 23:33:44
nit: of of -> of
jar (doing other things)
2011/11/18 23:57:41
Done.
| |
| 170 // relationships for tasks. This should be done by detecting what tasks are | |
| 171 // Born during the running of a parent task. The resulting data can be used by | |
| 172 // a smarter profiler to aggregate the cost of a series of child tasks into | |
| 173 // the ancestor task. It can also be used to illuminate what child or parent is | |
| 174 // related to each task. | |
| 175 // | |
| 176 // TODO(jar): We need to store DataCollections, and provide facilities for | |
| 177 // taking the difference between two gathered DataCollections. For now, we're | |
| 178 // just adding a hack that Reset()s to zero all counts and stats. This is also | |
| 162 // done in a slighly thread-unsafe fashion, as the resetting is done | 179 // done in a slighly thread-unsafe fashion, as the resetting is done |
| 163 // asynchronously relative to ongoing updates (but all data is 32 bit in size). | 180 // asynchronously relative to ongoing updates (but all data is 32 bit in size). |
| 164 // For basic profiling, this will work "most of the time," and should be | 181 // For basic profiling, this will work "most of the time," and should be |
| 165 // sufficient... but storing away DataCollections is the "right way" to do this. | 182 // sufficient... but storing away DataCollections is the "right way" to do this. |
| 166 // We'll accomplish this via JavaScript storage of snapshots, and then we'll | 183 // We'll accomplish this via JavaScript storage of snapshots, and then we'll |
| 167 // remove the Reset() methods. | 184 // remove the Reset() methods. We may also need a short-term-max value in |
| 185 // DeathData that is reset (as synchronously as possible) during each snapshot. | |
| 186 // This will facilitate displaying a max value for each snapshot period. | |
| 168 | 187 |
| 169 class MessageLoop; | 188 class MessageLoop; |
| 170 | 189 |
| 171 namespace tracked_objects { | 190 namespace tracked_objects { |
| 172 | 191 |
| 173 //------------------------------------------------------------------------------ | 192 //------------------------------------------------------------------------------ |
| 174 // For a specific thread, and a specific birth place, the collection of all | 193 // For a specific thread, and a specific birth place, the collection of all |
| 175 // death info (with tallies for each death thread, to prevent access conflicts). | 194 // death info (with tallies for each death thread, to prevent access conflicts). |
| 176 class ThreadData; | 195 class ThreadData; |
| 177 class BASE_EXPORT BirthOnThread { | 196 class BASE_EXPORT BirthOnThread { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 DurationInt AverageMsRunDuration() const; | 266 DurationInt AverageMsRunDuration() const; |
| 248 DurationInt run_duration_max() const { return run_time_.max(); } | 267 DurationInt run_duration_max() const { return run_time_.max(); } |
| 249 DurationInt queue_duration() const { return queue_time_.duration(); } | 268 DurationInt queue_duration() const { return queue_time_.duration(); } |
| 250 DurationInt AverageMsQueueDuration() const; | 269 DurationInt AverageMsQueueDuration() const; |
| 251 DurationInt queue_duration_max() const { return queue_time_.max(); } | 270 DurationInt queue_duration_max() const { return queue_time_.max(); } |
| 252 | 271 |
| 253 // Accumulate metrics from other into this. This method is never used on | 272 // Accumulate metrics from other into this. This method is never used on |
| 254 // realtime statistics, and only used in snapshots and aggregatinos. | 273 // realtime statistics, and only used in snapshots and aggregatinos. |
| 255 void AddDeathData(const DeathData& other); | 274 void AddDeathData(const DeathData& other); |
| 256 | 275 |
| 257 // Simple print of internal state for use in line of HTML. | |
| 258 void WriteHTML(std::string* output) const; | |
| 259 | |
| 260 // Construct a DictionaryValue instance containing all our stats. The caller | 276 // Construct a DictionaryValue instance containing all our stats. The caller |
| 261 // assumes ownership of the returned instance. | 277 // assumes ownership of the returned instance. |
| 262 base::DictionaryValue* ToValue() const; | 278 base::DictionaryValue* ToValue() const; |
| 263 | 279 |
| 264 // Reset all tallies to zero. This is used as a hack on realtime data. | 280 // Reset all tallies to zero. This is used as a hack on realtime data. |
| 265 void Clear(); | 281 void Clear(); |
| 266 | 282 |
| 267 private: | 283 private: |
| 268 // DeathData::Data is a helper class, useful when different metrics need to be | 284 // DeathData::Data is a helper class, useful when different metrics need to be |
| 269 // aggregated, such as queueing times, or run times. | 285 // aggregated, such as queueing times, or run times. |
| 270 class Data { | 286 class Data { |
| 271 public: | 287 public: |
| 272 Data() : duration_(0), max_(0) {} | 288 Data() : duration_(0), max_(0) {} |
| 273 ~Data() {} | 289 ~Data() {} |
| 274 | 290 |
| 275 DurationInt duration() const { return duration_; } | 291 DurationInt duration() const { return duration_; } |
| 276 DurationInt max() const { return max_; } | 292 DurationInt max() const { return max_; } |
| 277 | 293 |
| 278 // Emits HTML formated description of members, assuming |count| instances | |
| 279 // when calculating averages. | |
| 280 void WriteHTML(int count, std::string* output) const; | |
| 281 | |
| 282 // Agggegate data into our state. | 294 // Agggegate data into our state. |
| 283 void AddData(const Data& other); | 295 void AddData(const Data& other); |
| 284 void AddDuration(DurationInt duration); | 296 void AddDuration(DurationInt duration); |
| 285 | 297 |
| 286 // Central helper function for calculating averages (correctly, in only one | 298 // Central helper function for calculating averages (correctly, in only one |
| 287 // place). | 299 // place). |
| 288 DurationInt AverageMsDuration(int count) const; | 300 DurationInt AverageMsDuration(int count) const; |
| 289 | 301 |
| 290 // Resets all members to zero. | 302 // Resets all members to zero. |
| 291 void Clear(); | 303 void Clear(); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 479 // The following functions should all be private, and are only public because | 491 // The following functions should all be private, and are only public because |
| 480 // the collection is done externally. We need to relocate that code from the | 492 // the collection is done externally. We need to relocate that code from the |
| 481 // collection class into this class, and then all these methods can be made | 493 // collection class into this class, and then all these methods can be made |
| 482 // private. | 494 // private. |
| 483 // (Thread safe) Get start of list of all ThreadData instances. | 495 // (Thread safe) Get start of list of all ThreadData instances. |
| 484 static ThreadData* first(); | 496 static ThreadData* first(); |
| 485 // Iterate through the null terminated list of ThreadData instances. | 497 // Iterate through the null terminated list of ThreadData instances. |
| 486 ThreadData* next() const { return next_; } | 498 ThreadData* next() const { return next_; } |
| 487 // Using our lock, make a copy of the specified maps. These calls may arrive | 499 // Using our lock, make a copy of the specified maps. These calls may arrive |
| 488 // from non-local threads, and are used to quickly scan data from all threads | 500 // from non-local threads, and are used to quickly scan data from all threads |
| 489 // in order to build an HTML page for about:profiler. | 501 // in order to build JSON for about:profiler. |
| 490 void SnapshotBirthMap(BirthMap *output) const; | 502 void SnapshotBirthMap(BirthMap *output) const; |
| 491 void SnapshotDeathMap(DeathMap *output) const; | 503 void SnapshotDeathMap(DeathMap *output) const; |
| 492 // -------- end of should be private methods. | 504 // -------- end of should be private methods. |
| 493 | 505 |
| 494 // Hack: asynchronously clear all birth counts and death tallies data values | 506 // Hack: asynchronously clear all birth counts and death tallies data values |
| 495 // in all ThreadData instances. The numerical (zeroing) part is done without | 507 // in all ThreadData instances. The numerical (zeroing) part is done without |
| 496 // use of a locks or atomics exchanges, and may (for int64 values) produce | 508 // use of a locks or atomics exchanges, and may (for int64 values) produce |
| 497 // bogus counts VERY rarely. | 509 // bogus counts VERY rarely. |
| 498 static void ResetAllThreadData(); | 510 static void ResetAllThreadData(); |
| 499 | 511 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 518 // the profiler enabled. It will generally be optimized away when it is | 530 // the profiler enabled. It will generally be optimized away when it is |
| 519 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of | 531 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of |
| 520 // the code). | 532 // the code). |
| 521 static TrackedTime Now(); | 533 static TrackedTime Now(); |
| 522 | 534 |
| 523 private: | 535 private: |
| 524 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it | 536 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it |
| 525 // in production code. | 537 // in production code. |
| 526 friend class TrackedObjectsTest; | 538 friend class TrackedObjectsTest; |
| 527 | 539 |
| 528 // Implment a stack that avoids allocations during a push() by having enough | |
| 529 // space ahead of time. | |
| 530 class ThreadDataPool { | |
| 531 public: | |
| 532 ThreadDataPool(); | |
| 533 ~ThreadDataPool(); | |
| 534 | |
| 535 // Make sure the stack is large enough to support the indicated number of | |
| 536 // elements. | |
| 537 void reserve(size_t largest_worker_pool_number); | |
| 538 | |
| 539 bool empty() const; | |
| 540 const ThreadData* top() const; | |
| 541 void push(const ThreadData* thread_data); | |
| 542 void pop(); | |
| 543 | |
| 544 private: | |
| 545 std::vector<const ThreadData*> stack_; | |
| 546 size_t empty_slot_; | |
| 547 DISALLOW_COPY_AND_ASSIGN(ThreadDataPool); | |
| 548 }; | |
| 549 | |
| 550 // Worker thread construction creates a name since there is none. | 540 // Worker thread construction creates a name since there is none. |
| 551 explicit ThreadData(size_t thread_number); | 541 explicit ThreadData(int thread_number); |
| 552 | 542 |
| 553 // Message loop based construction should provide a name. | 543 // Message loop based construction should provide a name. |
| 554 explicit ThreadData(const std::string& suggested_name); | 544 explicit ThreadData(const std::string& suggested_name); |
| 555 | 545 |
| 556 ~ThreadData(); | 546 ~ThreadData(); |
| 557 | 547 |
| 558 // Push this instance to the head of all_thread_data_list_head_, linking it to | 548 // Push this instance to the head of all_thread_data_list_head_, linking it to |
| 559 // the previous head. This is performed after each construction, and leaves | 549 // the previous head. This is performed after each construction, and leaves |
| 560 // the instance permanently on that list. | 550 // the instance permanently on that list. |
| 561 void PushToHeadOfList(); | 551 void PushToHeadOfList(); |
| 562 | 552 |
| 563 // In this thread's data, record a new birth. | 553 // In this thread's data, record a new birth. |
| 564 Births* TallyABirth(const Location& location); | 554 Births* TallyABirth(const Location& location); |
| 565 | 555 |
| 566 // Find a place to record a death on this thread. | 556 // Find a place to record a death on this thread. |
| 567 void TallyADeath(const Births& birth, | 557 void TallyADeath(const Births& birth, |
| 568 DurationInt queue_duration, | 558 DurationInt queue_duration, |
| 569 DurationInt duration); | 559 DurationInt duration); |
| 570 | 560 |
| 571 // Using our lock to protect the iteration, Clear all birth and death data. | 561 // Using our lock to protect the iteration, Clear all birth and death data. |
| 572 void Reset(); | 562 void Reset(); |
| 573 | 563 |
| 574 // This method is called by the TLS system when a thread terminates. | 564 // This method is called by the TLS system when a thread terminates. |
| 575 // The argument may be NULL if this thread has never tracked a birth or death. | 565 // The argument may be NULL if this thread has never tracked a birth or death. |
| 576 static void OnThreadTermination(void* thread_data); | 566 static void OnThreadTermination(void* thread_data); |
| 577 | 567 |
| 578 // This method should be called when a worker thread terminates, so that we | 568 // This method should be called when a worker thread terminates, so that we |
| 579 // can save all the thread data into a cache of reusable ThreadData instances. | 569 // can save all the thread data into a cache of reusable ThreadData instances. |
| 580 void OnThreadTerminationCleanup() const; | 570 void OnThreadTerminationCleanup(); |
| 581 | 571 |
| 582 // Cleans up data structures, and returns statics to near pristine (mostly | 572 // Cleans up data structures, and returns statics to near pristine (mostly |
| 583 // uninitialized) state. If there is any chance that other threads are still | 573 // uninitialized) state. If there is any chance that other threads are still |
| 584 // using the data structures, then the |leak| argument should be passed in as | 574 // using the data structures, then the |leak| argument should be passed in as |
| 585 // true, and the data structures (birth maps, death maps, ThreadData | 575 // true, and the data structures (birth maps, death maps, ThreadData |
| 586 // insntances, etc.) will be leaked and not deleted. If you have joined all | 576 // insntances, etc.) will be leaked and not deleted. If you have joined all |
| 587 // threads since the time that InitializeAndSetTrackingStatus() was called, | 577 // threads since the time that InitializeAndSetTrackingStatus() was called, |
| 588 // then you can pass in a |leak| value of false, and this function will | 578 // then you can pass in a |leak| value of false, and this function will |
| 589 // delete recursively all data structures, starting with the list of | 579 // delete recursively all data structures, starting with the list of |
| 590 // ThreadData instances. | 580 // ThreadData instances. |
| 591 static void ShutdownSingleThreadedCleanup(bool leak); | 581 static void ShutdownSingleThreadedCleanup(bool leak); |
| 592 | 582 |
| 593 // We use thread local store to identify which ThreadData to interact with. | 583 // We use thread local store to identify which ThreadData to interact with. |
| 594 static base::ThreadLocalStorage::Slot tls_index_; | 584 static base::ThreadLocalStorage::Slot tls_index_; |
| 595 | 585 |
| 586 // List of ThreadData instances for use with worker threads. When a worker | |
| 587 // thread is done (terminated), we push it onto this llist. When a new worker | |
| 588 // thread is created, we first try to re-use a ThreadData instance from the | |
| 589 // list, and if none are available, construct a new one. | |
| 590 // This is only accessed while list_lock_ is held. | |
| 591 static ThreadData* first_retired_worker_; | |
| 592 | |
| 596 // Link to the most recently created instance (starts a null terminated list). | 593 // Link to the most recently created instance (starts a null terminated list). |
| 597 // The list is traversed by about:profiler when it needs to snapshot data. | 594 // The list is traversed by about:profiler when it needs to snapshot data. |
| 598 // This is only accessed while list_lock_ is held. | 595 // This is only accessed while list_lock_ is held. |
| 599 static ThreadData* all_thread_data_list_head_; | 596 static ThreadData* all_thread_data_list_head_; |
| 600 // Set of ThreadData instances for use with worker threads. When a worker | |
| 601 // thread is done (terminating), we push it into this pool. When a new worker | |
| 602 // thread is created, we first try to re-use a ThreadData instance from the | |
| 603 // pool, and if none are available, construct a new one. | |
| 604 // This is only accessed while list_lock_ is held. | |
| 605 static ThreadDataPool* unregistered_thread_data_pool_; | |
| 606 // The next available thread number. This should only be accessed when the | 597 // The next available thread number. This should only be accessed when the |
| 607 // list_lock_ is held. | 598 // list_lock_ is held. |
| 608 static int thread_number_counter_; | 599 static int thread_number_counter_; |
| 609 // Incarnation sequence number, indicating how many times (during unittests) | 600 // Incarnation sequence number, indicating how many times (during unittests) |
| 610 // we've either transitioned out of UNINITIALIZED, or into that state. This | 601 // we've either transitioned out of UNINITIALIZED, or into that state. This |
| 611 // value is only accessed while the list_lock_ is held. | 602 // value is only accessed while the list_lock_ is held. |
| 612 static int incarnation_counter_; | 603 static int incarnation_counter_; |
| 613 // Protection for access to all_thread_data_list_head_, and to | 604 // Protection for access to all_thread_data_list_head_, and to |
| 614 // unregistered_thread_data_pool_. This lock is leaked at shutdown. | 605 // unregistered_thread_data_pool_. This lock is leaked at shutdown. |
| 615 // The lock is very infrequently used, so we can afford to just make a lazy | 606 // The lock is very infrequently used, so we can afford to just make a lazy |
| 616 // instance and be safe. | 607 // instance and be safe. |
| 617 static base::LazyInstance<base::Lock, | 608 static base::LazyInstance<base::Lock, |
| 618 base::LeakyLazyInstanceTraits<base::Lock> > list_lock_; | 609 base::LeakyLazyInstanceTraits<base::Lock> > list_lock_; |
| 619 | 610 |
| 620 // Record of what the incarnation_counter_ was when this instance was created. | 611 // Record of what the incarnation_counter_ was when this instance was created. |
| 621 // If the incarnation_counter_ has changed, then we avoid pushing into the | 612 // If the incarnation_counter_ has changed, then we avoid pushing into the |
| 622 // pool (this is only critical in tests which go through multiple | 613 // pool (this is only critical in tests which go through multiple |
| 623 // incarations). | 614 // incarations). |
| 624 int incarnation_count_for_pool_; | 615 int incarnation_count_for_pool_; |
| 625 | 616 |
| 626 // We set status_ to SHUTDOWN when we shut down the tracking service. | 617 // We set status_ to SHUTDOWN when we shut down the tracking service. |
| 627 static Status status_; | 618 static Status status_; |
| 628 | 619 |
| 629 // Link to next instance (null terminated list). Used to globally track all | 620 // Link to next instance (null terminated list). Used to globally track all |
| 630 // registered instances (corresponds to all registered threads where we keep | 621 // registered instances (corresponds to all registered threads where we keep |
| 631 // data). | 622 // data). |
| 632 ThreadData* next_; | 623 ThreadData* next_; |
| 633 | 624 |
| 625 // Pointer to another ThreadData instance for a Worker-Thread that has been | |
| 626 // retired (its thread was terminated). This value is non-NULL only for a | |
| 627 // retired ThreadData associated with a Worker-Thread. | |
| 628 ThreadData* next_retired_worker_; | |
| 629 | |
| 634 // The name of the thread that is being recorded. If this thread has no | 630 // The name of the thread that is being recorded. If this thread has no |
| 635 // message_loop, then this is a worker thread, with a sequence number postfix. | 631 // message_loop, then this is a worker thread, with a sequence number postfix. |
| 636 std::string thread_name_; | 632 std::string thread_name_; |
| 637 | 633 |
| 638 // Indicate if this is a worker thread, and the ThreadData contexts should be | 634 // Indicate if this is a worker thread, and the ThreadData contexts should be |
| 639 // stored in the unregistered_thread_data_pool_ when not in use. | 635 // stored in the unregistered_thread_data_pool_ when not in use. |
| 640 // Value is zero when it is not a worker thread. Value is a positive integer | 636 // Value is zero when it is not a worker thread. Value is a positive integer |
| 641 // corresponding to the created thread name if it is a worker thread. | 637 // corresponding to the created thread name if it is a worker thread. |
| 642 size_t worker_thread_number_; | 638 int worker_thread_number_; |
| 643 | 639 |
| 644 // A map used on each thread to keep track of Births on this thread. | 640 // A map used on each thread to keep track of Births on this thread. |
| 645 // This map should only be accessed on the thread it was constructed on. | 641 // This map should only be accessed on the thread it was constructed on. |
| 646 // When a snapshot is needed, this structure can be locked in place for the | 642 // When a snapshot is needed, this structure can be locked in place for the |
| 647 // duration of the snapshotting activity. | 643 // duration of the snapshotting activity. |
| 648 BirthMap birth_map_; | 644 BirthMap birth_map_; |
| 649 | 645 |
| 650 // Similar to birth_map_, this records informations about death of tracked | 646 // Similar to birth_map_, this records informations about death of tracked |
| 651 // instances (i.e., when a tracked instance was destroyed on this thread). | 647 // instances (i.e., when a tracked instance was destroyed on this thread). |
| 652 // It is locked before changing, and hence other threads may access it by | 648 // It is locked before changing, and hence other threads may access it by |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 684 } | 680 } |
| 685 | 681 |
| 686 private: | 682 private: |
| 687 | 683 |
| 688 DISALLOW_COPY_AND_ASSIGN(AutoTracking); | 684 DISALLOW_COPY_AND_ASSIGN(AutoTracking); |
| 689 }; | 685 }; |
| 690 | 686 |
| 691 } // namespace tracked_objects | 687 } // namespace tracked_objects |
| 692 | 688 |
| 693 #endif // BASE_TRACKED_OBJECTS_H_ | 689 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |