1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_METRICS_HISTOGRAM_SYNCHRONIZER_H_
#define CHROME_BROWSER_METRICS_HISTOGRAM_SYNCHRONIZER_H_
#pragma once
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/condition_variable.h"
#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/time.h"
class MessageLoop;
class Task;
class HistogramSynchronizer : public
base::RefCountedThreadSafe<HistogramSynchronizer> {
public:
enum RendererHistogramRequester {
ASYNC_HISTOGRAMS,
SYNCHRONOUS_HISTOGRAMS
};
HistogramSynchronizer();
~HistogramSynchronizer();
// Return pointer to the singleton instance, which is allocated and
// deallocated on the main UI thread (during system startup and teardown).
static HistogramSynchronizer* CurrentSynchronizer();
// Contact all renderers, and get them to upload to the browser any/all
// changes to histograms. Return when all changes have been acquired, or when
// the wait time expires (whichever is sooner). This method is called on the
// main UI thread from about:histograms.
void FetchRendererHistogramsSynchronously(base::TimeDelta wait_time);
// Contact all renderers, and get them to upload to the browser any/all
// changes to histograms. When all changes have been acquired, or when the
// wait time expires (whichever is sooner), post the callback_task to the UI
// thread. Note the callback_task is posted exactly once. This method is
// called on the IO thread from UMA via PostMessage.
static void FetchRendererHistogramsAsynchronously(
MessageLoop* callback_thread, Task* callback_task, int wait_time);
// This method is called on the IO thread. Desrializes the histograms and
// records that we have received histograms from a renderer process.
static void DeserializeHistogramList(
int sequence_number, const std::vector<std::string>& histograms);
private:
// Records that we have received the histograms from a renderer for the given
// sequence number. If we have received a response from all histograms, either
// signal the waiting process or call the callback function. Returns true when
// we receive histograms from the last of N renderers that were contacted for
// an update. This is called on IO Thread.
bool RecordRendererHistogram(int sequence_number);
void SetCallbackTaskToCallAfterGettingHistograms(
MessageLoop* callback_thread, Task* callback_task);
void ForceHistogramSynchronizationDoneCallback(int sequence_number);
// Calls the callback task, if there is a callback_task.
void CallCallbackTaskAndResetData();
// Gets a new sequence number to be sent to renderers from browser process.
// This will also reset the current pending renderers for the given type.
int GetNextAvaibleSequenceNumber(RendererHistogramRequester requster);
// Increments the count of the renderers we're waiting for for the request
// of the given type.
void IncrementPendingRenderers(RendererHistogramRequester requester);
// For use ONLY in a DCHECK. This method initializes io_message_loop_ in its
// first call and then compares io_message_loop_ with MessageLoop::current()
// in subsequent calls. This method guarantees we're consistently on the
// singular IO thread and we don't need to worry about locks.
bool IsOnIoThread();
// This lock_ protects access to sequence number and
// synchronous_renderers_pending_.
Lock lock_;
// This condition variable is used to block caller of the synchronous request
// to update histograms, and to signal that thread when updates are completed.
ConditionVariable received_all_renderer_historgrams_;
// When a request is made to asynchronously update the histograms, we store
// the task and thread we use to post a completion notification in
// callback_task_ and callback_thread_.
Task* callback_task_;
MessageLoop* callback_thread_;
// For use ONLY in a DCHECK and is used in IsOnIoThread(). io_message_loop_ is
// initialized during the first call to IsOnIoThread(), and then compares
// MessageLoop::current() against io_message_loop_ in subsequent calls for
// consistency.
MessageLoop* io_message_loop_;
// We don't track the actual renderers that are contacted for an update, only
// the count of the number of renderers, and we can sometimes time-out and
// give up on a "slow to respond" renderer. We use a sequence_number to be
// sure a response from a renderer is associated with the current round of
// requests (and not merely a VERY belated prior response).
// next_available_sequence_number_ is the next available number (used to
// avoid reuse for a long time).
int next_available_sequence_number_;
// The sequence number used by the most recent asynchronous update request to
// contact all renderers.
int async_sequence_number_;
// The number of renderers that have not yet responded to requests (as part of
// an asynchronous update).
int async_renderers_pending_;
// The time when we were told to start the fetch histograms asynchronously
// from renderers.
base::TimeTicks async_callback_start_time_;
// The sequence number used by the most recent synchronous update request to
// contact all renderers.
int synchronous_sequence_number_;
// The number of renderers that have not yet responded to requests (as part of
// a synchronous update).
int synchronous_renderers_pending_;
// This singleton instance should be started during the single threaded
// portion of main(). It initializes globals to provide support for all future
// calls. This object is created on the UI thread, and it is destroyed after
// all the other threads have gone away. As a result, it is ok to call it
// from the UI thread (for UMA uploads), or for about:histograms.
static HistogramSynchronizer* histogram_synchronizer_;
DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
};
#endif // CHROME_BROWSER_METRICS_HISTOGRAM_SYNCHRONIZER_H_
|