// For each thread, we have a ThreadData that stores all tracking info generated // on this thread. This prevents the need for locking as data accumulates.
看看头文件
class ThreadData { public: typedef std::map<Location, Births*> BirthMap; typedef std::map<const Births*, DeathData> DeathMap; ThreadData(); // Using Thread Local Store, find the current instance for collecting data. // If an instance does not exist, construct one (and remember it for use on // this thread. // If shutdown has already started, and we don't yet have an instance, then // return null. static ThreadData* current(); // For a given about:objects URL, develop resulting HTML, and append to // output. static void WriteHTML(const std::string& query, std::string* output); // For a given accumulated array of results, use the comparator to sort and // subtotal, writing the results to the output. static void WriteHTMLTotalAndSubtotals( const DataCollector::Collection& match_array, const Comparator& comparator, std::string* output); // In this thread's data, find a place to record a new birth. Births* FindLifetime(const Location& location); // Find a place to record a death on this thread. void TallyADeath(const Births& lifetimes, const base::TimeDelta& duration); // (Thread safe) Get start of list of instances. static ThreadData* first(); // Iterate through the null terminated list of instances. ThreadData* next() const { return next_; } MessageLoop* message_loop() const { return message_loop_; } const std::string ThreadName() const; // Using our lock, make a copy of the specified maps. These calls may arrive // from non-local threads. void SnapshotBirthMap(BirthMap *output) const; void SnapshotDeathMap(DeathMap *output) const; static void RunOnAllThreads(void (*Func)()); // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN, // based on argument being true or false respectively. // IF tracking is not compiled in, this function will return false. static bool StartTracking(bool status); static bool IsActive(); #ifdef OS_WIN // WARNING: ONLY call this function when all MessageLoops are still intact for // all registered threads. IF you call it later, you will crash. // Note: You don't need to call it at all, and you can wait till you are // single threaded (again) to do the cleanup via // ShutdownSingleThreadedCleanup(). // Start the teardown (shutdown) process in a multi-thread mode by disabling // further additions to thread database on all threads. First it makes a // local (locked) change to prevent any more threads from registering. Then // it Posts a Task to all registered threads to be sure they are aware that no // more accumulation can take place. static void ShutdownMultiThreadTracking(); #endif // WARNING: ONLY call this function when you are running single threaded // (again) and all message loops and threads have terminated. Until that // point some threads may still attempt to write into our data structures. // Delete recursively all data structures, starting with the list of // ThreadData instances. static void ShutdownSingleThreadedCleanup();
大致想想怎么用
1. 开始
开始运行,
StartTracking(true)
2. 结束,并输出
StartTracking(false)
WriteHTML(...)
有个测试用例,可以看看
TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { // Minimal test doesn't even create any tasks. if (!ThreadData::StartTracking(true)) return; EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. ThreadData* data = ThreadData::current(); EXPECT_TRUE(ThreadData::first()); // Now class was constructed. EXPECT_TRUE(data); EXPECT_TRUE(!data->next()); EXPECT_EQ(data, ThreadData::current()); ThreadData::BirthMap birth_map; data->SnapshotBirthMap(&birth_map); // Get all birth data EXPECT_EQ(0u, birth_map.size()); ThreadData::DeathMap death_map; data->SnapshotDeathMap(&death_map); EXPECT_EQ(0u, death_map.size()); ThreadData::ShutdownSingleThreadedCleanup(); // Do it again, just to be sure we reset state completely. ThreadData::StartTracking(true); EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. data = ThreadData::current(); EXPECT_TRUE(ThreadData::first()); // Now class was constructed. EXPECT_TRUE(data); EXPECT_TRUE(!data->next()); EXPECT_EQ(data, ThreadData::current()); birth_map.clear(); data->SnapshotBirthMap(&birth_map); EXPECT_EQ(0u, birth_map.size()); death_map.clear(); data->SnapshotDeathMap(&death_map); EXPECT_EQ(0u, death_map.size()); ThreadData::ShutdownSingleThreadedCleanup(); }