diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/content/browser/histogram_synchronizer.h | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'chromium/content/browser/histogram_synchronizer.h')
-rw-r--r-- | chromium/content/browser/histogram_synchronizer.h | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/chromium/content/browser/histogram_synchronizer.h b/chromium/content/browser/histogram_synchronizer.h new file mode 100644 index 00000000000..9ff69d5cfeb --- /dev/null +++ b/chromium/content/browser/histogram_synchronizer.h @@ -0,0 +1,154 @@ +// Copyright (c) 2012 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 CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_ +#define CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/singleton.h" +#include "base/synchronization/lock.h" +#include "base/time/time.h" +#include "content/browser/histogram_subscriber.h" + +namespace base { +class MessageLoop; +} + +namespace content { + +// This class maintains state that is used to upload histogram data from the +// various child processes, into the browser process. Such transactions are +// usually instigated by the browser. In general, a child process will respond +// by gathering snapshots of all internal histograms, calculating what has +// changed since its last upload, and transmitting a pickled collection of +// deltas. +// +// There are actually two modes of update request. One is synchronous (and +// blocks the UI thread, waiting to populate an about:histograms tab) and the +// other is asynchronous, and used by the metrics services in preparation for a +// log upload. +// +// To assure that all the processes have responded, a counter is maintained to +// indicate the number of pending (not yet responsive) processes. To avoid +// confusion about a response (i.e., is the process responding to a current +// request for an update, or to an old request for an update) we tag each group +// of requests with a sequence number. When an update arrives we can ignore it +// (relative to the counter) if it does not relate to a current outstanding +// sequence number. +// +// There is one final mode of use, where a renderer spontaneously decides to +// transmit a collection of histogram data. This is designed for use when the +// renderer is terminating. Unfortunately, renders may be terminated without +// warning, and the best we can do is periodically acquire data from a tab, such +// as when a page load has completed. In this mode, the renderer uses a +// reserved sequence number, different from any sequence number that might be +// specified by a browser request. Since this sequence number can't match an +// outstanding sequence number, the pickled data is accepted into the browser, +// but there is no impact on the counters. + +class HistogramSynchronizer : public HistogramSubscriber { + public: + enum ProcessHistogramRequester { + UNKNOWN, + ASYNC_HISTOGRAMS, + }; + + // Return pointer to the singleton instance for the current process, or NULL + // if none. + static HistogramSynchronizer* GetInstance(); + + // Contact all processes, and get them to upload to the browser any/all + // changes to histograms. This method is called from about:histograms. + static void FetchHistograms(); + + // Contact all child processes, 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 to the + // specified message loop. Note the callback is posted exactly once. + static void FetchHistogramsAsynchronously(base::MessageLoop* callback_thread, + const base::Closure& callback, + base::TimeDelta wait_time); + + private: + friend struct DefaultSingletonTraits<HistogramSynchronizer>; + + class RequestContext; + + HistogramSynchronizer(); + virtual ~HistogramSynchronizer(); + + // Establish a new sequence number, and use it to notify all processes + // (renderers, plugins, GPU, etc) of the need to supply, to the browser, + // any/all changes to their histograms. |wait_time| specifies the amount of + // time to wait before cancelling the requests for non-responsive processes. + void RegisterAndNotifyAllProcesses(ProcessHistogramRequester requester, + base::TimeDelta wait_time); + + // ------------------------------------------------------- + // HistogramSubscriber methods for browser child processes + // ------------------------------------------------------- + + // Update the number of pending processes for the given |sequence_number|. + // This is called on UI thread. + virtual void OnPendingProcesses(int sequence_number, + int pending_processes, + bool end) OVERRIDE; + + // Send histogram_data back to caller and also record that we are waiting + // for one less histogram data from child process for the given sequence + // number. This method is accessible on UI thread. + virtual void OnHistogramDataCollected( + int sequence_number, + const std::vector<std::string>& pickled_histograms) OVERRIDE; + + // Set the callback_thread_ and callback_ members. If these members already + // had values, then as a side effect, post the old callback_ to the old + // callaback_thread_. This side effect should not generally happen, but is in + // place to assure correctness (that any tasks that were set, are eventually + // called, and never merely discarded). + void SetCallbackTaskAndThread(base::MessageLoop* callback_thread, + const base::Closure& callback); + + void ForceHistogramSynchronizationDoneCallback(int sequence_number); + + // Internal helper function, to post task, and record callback stats. + void InternalPostTask(base::MessageLoop* thread, + const base::Closure& callback); + + // Gets a new sequence number to be sent to processes from browser process. + int GetNextAvailableSequenceNumber(ProcessHistogramRequester requester); + + // This lock_ protects access to all members. + base::Lock lock_; + + // 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_ and callback_thread_. + base::Closure callback_; + base::MessageLoop* callback_thread_; + + // We don't track the actual processes that are contacted for an update, only + // the count of the number of processes, and we can sometimes time-out and + // give up on a "slow to respond" process. We use a sequence_number to be + // sure a response from a process is associated with the current round of + // requests (and not merely a VERY belated prior response). + // All sequence numbers used are non-negative. + // last_used_sequence_number_ is the most recently used number (used to avoid + // reuse for a long time). + int last_used_sequence_number_; + + // The sequence number used by the most recent asynchronous update request to + // contact all processes. + int async_sequence_number_; + + DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_ |