Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "chrome/browser/metrics/tracking_synchronizer.h" | 5 #include "chrome/browser/metrics/tracking_synchronizer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
| 10 #include "base/threading/thread.h" | 10 #include "base/threading/thread.h" |
| 11 #include "base/tracked_objects.h" | 11 #include "base/tracked_objects.h" |
| 12 #include "chrome/browser/metrics/tracking_synchronizer_observer.h" | |
| 12 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 13 #include "content/public/browser/profiler_controller.h" | 14 #include "content/public/browser/profiler_controller.h" |
| 14 #include "content/public/common/process_type.h" | |
| 15 | 15 |
| 16 using base::TimeTicks; | 16 using base::TimeTicks; |
| 17 using content::BrowserThread; | 17 using content::BrowserThread; |
| 18 | 18 |
| 19 namespace { | |
| 20 | |
| 21 // Negative numbers are never used as sequence numbers. We explicitly pick a | |
| 22 // negative number that is "so negative" that even when we add one (as is done | |
| 23 // when we generated the next sequence number) that it will still be negative. | |
| 24 // We have code that handles wrapping around on an overflow into negative | |
| 25 // territory. | |
| 26 const int kNeverUsableSequenceNumber = -2; | |
| 27 | |
| 28 // TODO(isherman): Is there any reason not to use base/singleton.h and instead | |
| 29 // roll our own version? | |
|
jar (doing other things)
2012/03/21 18:19:55
You'd have to look closely at the semantics we use
Ilya Sherman
2012/03/21 21:45:43
Ok. :)
| |
| 30 // This singleton instance should be started during the single threaded | |
| 31 // portion of main(). It initializes globals to provide support for all future | |
| 32 // calls. This object is created on the UI thread, and it is destroyed after | |
| 33 // all the other threads have gone away. As a result, it is ok to call it | |
| 34 // from the UI thread, or for about:profiler. | |
| 35 static chrome_browser_metrics::TrackingSynchronizer* g_tracking_synchronizer = | |
| 36 NULL; | |
| 37 | |
| 38 } // anonymous namespace | |
| 39 | |
| 19 namespace chrome_browser_metrics { | 40 namespace chrome_browser_metrics { |
| 20 | 41 |
| 21 // The "RequestContext" structure describes an individual request received | 42 // The "RequestContext" structure describes an individual request received |
| 22 // from the UI. All methods are accessible on UI thread. | 43 // from the UI. All methods are accessible on UI thread. |
| 23 class RequestContext { | 44 class TrackingSynchronizer::RequestContext { |
| 24 public: | 45 public: |
| 25 // A map from sequence_number_ to the actual RequestContexts. | 46 // A map from sequence_number_ to the actual RequestContexts. |
| 26 typedef std::map<int, RequestContext*> RequestContextMap; | 47 typedef std::map<int, RequestContext*> RequestContextMap; |
| 27 | 48 |
| 28 ~RequestContext() {} | 49 RequestContext( |
| 29 | 50 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object, |
| 30 RequestContext(const base::WeakPtr<ProfilerUI>& callback_object, | 51 int sequence_number) |
| 31 int sequence_number) | |
| 32 : callback_object_(callback_object), | 52 : callback_object_(callback_object), |
| 33 sequence_number_(sequence_number), | 53 sequence_number_(sequence_number), |
| 34 received_process_group_count_(0), | 54 received_process_group_count_(0), |
| 35 processes_pending_(0) { | 55 processes_pending_(0) { |
| 36 } | 56 } |
| 57 ~RequestContext() {} | |
| 37 | 58 |
| 38 void SetReceivedProcessGroupCount(bool done) { | 59 void SetReceivedProcessGroupCount(bool done) { |
| 39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 40 received_process_group_count_ = done; | 61 received_process_group_count_ = done; |
| 41 } | 62 } |
| 42 | 63 |
| 43 // Methods for book keeping of processes_pending_. | 64 // Methods for book keeping of processes_pending_. |
| 44 void IncrementProcessesPending() { | 65 void IncrementProcessesPending() { |
| 45 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 46 ++processes_pending_; | 67 ++processes_pending_; |
| 47 } | 68 } |
| 48 | 69 |
| 49 void AddProcessesPending(int processes_pending) { | 70 void AddProcessesPending(int processes_pending) { |
| 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 51 processes_pending_ += processes_pending; | 72 processes_pending_ += processes_pending; |
| 52 } | 73 } |
| 53 | 74 |
| 54 void DecrementProcessesPending() { | 75 void DecrementProcessesPending() { |
| 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 56 --processes_pending_; | 77 --processes_pending_; |
| 57 } | 78 } |
| 58 | 79 |
| 59 // Records that we are waiting for one less tracking data from a process for | 80 // Records that we are waiting for one less tracking data from a process for |
| 60 // the given sequence number. If |received_process_group_count_| and | 81 // the given sequence number. If |received_process_group_count_| and |
| 61 // |processes_pending_| are zero, then delete the current object by calling | 82 // |processes_pending_| are zero, then delete the current object by calling |
| 62 // Unregister. | 83 // Unregister. |
| 63 void DeleteIfAllDone() { | 84 void DeleteIfAllDone() { |
| 64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 65 | 86 |
| 66 if (processes_pending_ <= 0 && received_process_group_count_) { | 87 if (processes_pending_ <= 0 && received_process_group_count_) |
| 67 RequestContext::Unregister(sequence_number_); | 88 RequestContext::Unregister(sequence_number_); |
| 68 } | |
| 69 } | 89 } |
| 70 | 90 |
| 71 | 91 |
| 72 // Register |callback_object| in |outstanding_requests_| map for the given | 92 // Register |callback_object| in |outstanding_requests_| map for the given |
| 73 // |sequence_number|. | 93 // |sequence_number|. |
| 74 static RequestContext* Register( | 94 static RequestContext* Register( |
| 75 int sequence_number, | 95 int sequence_number, |
| 76 const base::WeakPtr<ProfilerUI>& callback_object) { | 96 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { |
| 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 78 | 98 |
| 79 RequestContext* request = new RequestContext( | 99 RequestContext* request = new RequestContext( |
| 80 callback_object, sequence_number); | 100 callback_object, sequence_number); |
| 81 outstanding_requests_.Get()[sequence_number] = request; | 101 outstanding_requests_.Get()[sequence_number] = request; |
| 82 | 102 |
| 83 return request; | 103 return request; |
| 84 } | 104 } |
| 85 | 105 |
| 86 // Find the |RequestContext| in |outstanding_requests_| map for the given | 106 // Find the |RequestContext| in |outstanding_requests_| map for the given |
| 87 // |sequence_number|. | 107 // |sequence_number|. |
| 88 static RequestContext* GetRequestContext(int sequence_number) { | 108 static RequestContext* GetRequestContext(int sequence_number) { |
| 89 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 90 | 110 |
| 91 RequestContextMap::iterator it = | 111 RequestContextMap::iterator it = |
| 92 outstanding_requests_.Get().find(sequence_number); | 112 outstanding_requests_.Get().find(sequence_number); |
| 93 if (it == outstanding_requests_.Get().end()) | 113 if (it == outstanding_requests_.Get().end()) |
| 94 return NULL; | 114 return NULL; |
| 95 | 115 |
| 96 RequestContext* request = NULL; | 116 RequestContext* request = it->second; |
| 97 request = it->second; | 117 DCHECK_EQ(sequence_number, request->sequence_number_); |
| 98 DCHECK(sequence_number == request->sequence_number_); | |
| 99 return request; | 118 return request; |
| 100 } | 119 } |
| 101 | 120 |
| 102 // Delete the entry for the given sequence_number| from | 121 // Delete the entry for the given sequence_number| from |
| 103 // |outstanding_requests_| map. This method is called when all changes have | 122 // |outstanding_requests_| map. This method is called when all changes have |
| 104 // been acquired, or when the wait time expires (whichever is sooner). | 123 // been acquired, or when the wait time expires (whichever is sooner). |
| 105 static void Unregister(int sequence_number) { | 124 static void Unregister(int sequence_number) { |
| 106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 107 | 126 |
| 108 RequestContextMap::iterator it = | 127 RequestContextMap::iterator it = |
| 109 outstanding_requests_.Get().find(sequence_number); | 128 outstanding_requests_.Get().find(sequence_number); |
| 110 if (it == outstanding_requests_.Get().end()) | 129 if (it == outstanding_requests_.Get().end()) |
| 111 return; | 130 return; |
| 112 | 131 |
| 113 RequestContext* request = it->second; | 132 RequestContext* request = it->second; |
| 114 DCHECK(sequence_number == request->sequence_number_); | 133 DCHECK_EQ(sequence_number, request->sequence_number_); |
| 115 bool received_process_group_count = request->received_process_group_count_; | 134 bool received_process_group_count = request->received_process_group_count_; |
| 116 int unresponsive_processes = request->processes_pending_; | 135 int unresponsive_processes = request->processes_pending_; |
| 117 | 136 |
| 118 delete it->second; | 137 request->callback_object_->FinishedReceivingProfilerData(); |
| 138 | |
| 139 delete request; | |
| 119 outstanding_requests_.Get().erase(it); | 140 outstanding_requests_.Get().erase(it); |
| 120 | 141 |
| 121 UMA_HISTOGRAM_BOOLEAN("Profiling.ReceivedProcessGroupCount", | 142 UMA_HISTOGRAM_BOOLEAN("Profiling.ReceivedProcessGroupCount", |
| 122 received_process_group_count); | 143 received_process_group_count); |
| 123 UMA_HISTOGRAM_COUNTS("Profiling.PendingProcessNotResponding", | 144 UMA_HISTOGRAM_COUNTS("Profiling.PendingProcessNotResponding", |
| 124 unresponsive_processes); | 145 unresponsive_processes); |
| 125 } | 146 } |
| 126 | 147 |
| 127 | 148 |
| 128 // Delete all the entries in |outstanding_requests_| map. | 149 // Delete all the entries in |outstanding_requests_| map. |
| 129 static void OnShutdown() { | 150 static void OnShutdown() { |
| 130 // Just in case we have any pending tasks, clear them out. | 151 // Just in case we have any pending tasks, clear them out. |
| 131 while (!outstanding_requests_.Get().empty()) { | 152 while (!outstanding_requests_.Get().empty()) { |
| 132 RequestContextMap::iterator it = outstanding_requests_.Get().begin(); | 153 RequestContextMap::iterator it = outstanding_requests_.Get().begin(); |
| 133 delete it->second; | 154 delete it->second; |
| 134 outstanding_requests_.Get().erase(it); | 155 outstanding_requests_.Get().erase(it); |
| 135 } | 156 } |
| 136 } | 157 } |
| 137 | 158 |
| 138 // Requests are made to asynchronously send data to the |callback_object_|. | 159 // Requests are made to asynchronously send data to the |callback_object_|. |
| 139 base::WeakPtr<ProfilerUI> callback_object_; | 160 base::WeakPtr<TrackingSynchronizerObserver> callback_object_; |
| 140 | 161 |
| 141 // The sequence number used by the most recent update request to contact all | 162 // The sequence number used by the most recent update request to contact all |
| 142 // processes. | 163 // processes. |
| 143 int sequence_number_; | 164 int sequence_number_; |
| 144 | 165 |
| 145 // Indicates if we have received all pending processes count. | 166 // Indicates if we have received all pending processes count. |
| 146 bool received_process_group_count_; | 167 bool received_process_group_count_; |
| 147 | 168 |
| 148 // The number of pending processes (browser, all renderer processes and | 169 // The number of pending processes (browser, all renderer processes and |
| 149 // browser child processes) that have not yet responded to requests. | 170 // browser child processes) that have not yet responded to requests. |
| 150 int processes_pending_; | 171 int processes_pending_; |
| 151 | 172 |
| 152 // Map of all outstanding RequestContexts, from sequence_number_ to | 173 // Map of all outstanding RequestContexts, from sequence_number_ to |
| 153 // RequestContext. | 174 // RequestContext. |
| 154 static base::LazyInstance<RequestContextMap> outstanding_requests_; | 175 static base::LazyInstance<RequestContextMap> outstanding_requests_; |
| 155 }; | 176 }; |
| 156 | 177 |
| 157 // Negative numbers are never used as sequence numbers. We explicitly pick a | 178 // static |
| 158 // negative number that is "so negative" that even when we add one (as is done | 179 base::LazyInstance<TrackingSynchronizer::RequestContext::RequestContextMap> |
| 159 // when we generated the next sequence number) that it will still be negative. | 180 TrackingSynchronizer::RequestContext::outstanding_requests_ = |
| 160 // We have code that handles wrapping around on an overflow into negative | 181 LAZY_INSTANCE_INITIALIZER; |
| 161 // territory. | |
| 162 static const int kNeverUsableSequenceNumber = -2; | |
| 163 | 182 |
| 164 // TrackingSynchronizer methods and members. | 183 // TrackingSynchronizer methods and members. |
| 165 // | |
| 166 // static | |
| 167 TrackingSynchronizer* TrackingSynchronizer::tracking_synchronizer_ = NULL; | |
| 168 | 184 |
| 169 TrackingSynchronizer::TrackingSynchronizer() | 185 TrackingSynchronizer::TrackingSynchronizer() |
| 170 : last_used_sequence_number_(kNeverUsableSequenceNumber) { | 186 : last_used_sequence_number_(kNeverUsableSequenceNumber) { |
| 171 DCHECK(tracking_synchronizer_ == NULL); | 187 DCHECK(!g_tracking_synchronizer); |
| 172 tracking_synchronizer_ = this; | 188 g_tracking_synchronizer = this; |
| 173 content::ProfilerController::GetInstance()->Register(this); | 189 content::ProfilerController::GetInstance()->Register(this); |
| 174 } | 190 } |
| 175 | 191 |
| 176 TrackingSynchronizer::~TrackingSynchronizer() { | 192 TrackingSynchronizer::~TrackingSynchronizer() { |
| 177 content::ProfilerController::GetInstance()->Unregister(this); | 193 content::ProfilerController::GetInstance()->Unregister(this); |
| 178 | 194 |
| 179 // Just in case we have any pending tasks, clear them out. | 195 // Just in case we have any pending tasks, clear them out. |
| 180 RequestContext::OnShutdown(); | 196 RequestContext::OnShutdown(); |
| 181 | 197 |
| 182 tracking_synchronizer_ = NULL; | 198 g_tracking_synchronizer = NULL; |
| 183 } | 199 } |
| 184 | 200 |
| 185 // static | 201 // static |
| 186 void TrackingSynchronizer::FetchProfilerDataAsynchronously( | 202 void TrackingSynchronizer::FetchProfilerDataAsynchronously( |
| 187 const base::WeakPtr<ProfilerUI>& callback_object) { | 203 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 | 205 |
| 190 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer(); | 206 if (!g_tracking_synchronizer) { |
| 191 if (current_synchronizer == NULL) { | |
| 192 // System teardown is happening. | 207 // System teardown is happening. |
| 193 return; | 208 return; |
| 194 } | 209 } |
| 195 | 210 |
| 196 int sequence_number = current_synchronizer->RegisterAndNotifyAllProcesses( | 211 int sequence_number = g_tracking_synchronizer->RegisterAndNotifyAllProcesses( |
| 197 callback_object); | 212 callback_object); |
| 198 | 213 |
| 199 // Post a task that would be called after waiting for wait_time. This acts | 214 // Post a task that would be called after waiting for wait_time. This acts |
| 200 // as a watchdog, to cancel the requests for non-responsive processes. | 215 // as a watchdog, to cancel the requests for non-responsive processes. |
| 201 BrowserThread::PostDelayedTask( | 216 BrowserThread::PostDelayedTask( |
| 202 BrowserThread::UI, FROM_HERE, | 217 BrowserThread::UI, FROM_HERE, |
| 203 base::Bind(&RequestContext::Unregister, sequence_number), | 218 base::Bind(&RequestContext::Unregister, sequence_number), |
| 204 base::TimeDelta::FromMinutes(1)); | 219 base::TimeDelta::FromMinutes(1)); |
| 205 } | 220 } |
| 206 | 221 |
| 207 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, | 222 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, |
| 208 int pending_processes, | 223 int pending_processes, |
| 209 bool end) { | 224 bool end) { |
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 211 | 226 |
| 212 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 227 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
| 213 if (!request) | 228 if (!request) |
| 214 return; | 229 return; |
| 215 request->AddProcessesPending(pending_processes); | 230 request->AddProcessesPending(pending_processes); |
| 216 request->SetReceivedProcessGroupCount(end); | 231 request->SetReceivedProcessGroupCount(end); |
| 217 request->DeleteIfAllDone(); | 232 request->DeleteIfAllDone(); |
| 218 } | 233 } |
| 219 | 234 |
| 220 void TrackingSynchronizer::OnProfilerDataCollected( | 235 void TrackingSynchronizer::OnProfilerDataCollected( |
| 221 int sequence_number, | 236 int sequence_number, |
| 222 base::DictionaryValue* profiler_data) { | 237 const tracked_objects::SerializedProcessData& profiler_data, |
| 238 content::ProcessType process_type) { | |
| 223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 224 | 240 DecrementPendingProcessesAndSendData(sequence_number, profiler_data, |
| 225 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 241 process_type); |
| 226 if (!request) | |
| 227 return; | |
| 228 | |
| 229 DecrementPendingProcessesAndSendData(sequence_number, profiler_data); | |
| 230 } | 242 } |
| 231 | 243 |
| 232 int TrackingSynchronizer::RegisterAndNotifyAllProcesses( | 244 int TrackingSynchronizer::RegisterAndNotifyAllProcesses( |
| 233 const base::WeakPtr<ProfilerUI>& callback_object) { | 245 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { |
| 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 235 | 247 |
| 236 int sequence_number = GetNextAvailableSequenceNumber(); | 248 int sequence_number = GetNextAvailableSequenceNumber(); |
| 237 | 249 |
| 238 RequestContext* request = | 250 RequestContext* request = |
| 239 RequestContext::Register(sequence_number, callback_object); | 251 RequestContext::Register(sequence_number, callback_object); |
| 240 | 252 |
| 241 // Increment pending process count for sending browser's profiler data. | 253 // Increment pending process count for sending browser's profiler data. |
| 242 request->IncrementProcessesPending(); | 254 request->IncrementProcessesPending(); |
| 243 | 255 |
| 244 // Get profiler data from renderer and browser child processes. | 256 // Get profiler data from renderer and browser child processes. |
| 245 content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); | 257 content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); |
| 246 | 258 |
| 247 // Send profiler_data from browser process. | 259 // Send profiler_data from browser process. |
| 248 base::DictionaryValue* value = tracked_objects::ThreadData::ToValue(false); | 260 tracked_objects::SerializedProcessData process_data; |
| 249 const std::string process_type = | 261 tracked_objects::ThreadData::ToSerializedProcessData(false, &process_data); |
| 250 content::GetProcessTypeNameInEnglish(content::PROCESS_TYPE_BROWSER); | 262 DecrementPendingProcessesAndSendData(sequence_number, process_data, |
| 251 value->SetString("process_type", process_type); | 263 content::PROCESS_TYPE_BROWSER); |
| 252 value->SetInteger("process_id", base::GetCurrentProcId()); | |
| 253 DecrementPendingProcessesAndSendData(sequence_number, value); | |
| 254 | 264 |
| 255 return sequence_number; | 265 return sequence_number; |
| 256 } | 266 } |
| 257 | 267 |
| 258 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( | 268 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( |
| 259 int sequence_number, | 269 int sequence_number, |
| 260 base::DictionaryValue* value) { | 270 const tracked_objects::SerializedProcessData& profiler_data, |
| 271 content::ProcessType process_type) { | |
| 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 262 | 273 |
| 263 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 274 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
| 264 if (!request) { | 275 if (!request) |
| 265 delete value; | |
| 266 return; | 276 return; |
| 267 } | |
| 268 | 277 |
| 269 if (value && request->callback_object_) { | 278 if (request->callback_object_) { |
| 270 // Transfers ownership of |value| to |callback_object_|. | 279 request->callback_object_->ReceivedProfilerData(profiler_data, |
| 271 request->callback_object_->ReceivedData(value); | 280 process_type); |
| 272 } else { | |
| 273 delete value; | |
| 274 } | 281 } |
| 275 | 282 |
| 276 // Delete request if we have heard back from all child processes. | 283 // Delete request if we have heard back from all child processes. |
| 277 request->DecrementProcessesPending(); | 284 request->DecrementProcessesPending(); |
| 278 request->DeleteIfAllDone(); | 285 request->DeleteIfAllDone(); |
| 279 } | 286 } |
| 280 | 287 |
| 281 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { | 288 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { |
| 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 283 | 290 |
| 284 ++last_used_sequence_number_; | 291 ++last_used_sequence_number_; |
| 285 | 292 |
| 286 // Watch out for wrapping to a negative number. | 293 // Watch out for wrapping to a negative number. |
| 287 if (last_used_sequence_number_ < 0) | 294 if (last_used_sequence_number_ < 0) |
| 288 last_used_sequence_number_ = 1; | 295 last_used_sequence_number_ = 1; |
| 289 return last_used_sequence_number_; | 296 return last_used_sequence_number_; |
| 290 } | 297 } |
| 291 | 298 |
| 292 // static | |
| 293 TrackingSynchronizer* TrackingSynchronizer::CurrentSynchronizer() { | |
| 294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 295 DCHECK(tracking_synchronizer_ != NULL); | |
| 296 return tracking_synchronizer_; | |
| 297 } | |
| 298 | |
| 299 // static | |
| 300 base::LazyInstance<RequestContext::RequestContextMap> | |
| 301 RequestContext::outstanding_requests_ = LAZY_INSTANCE_INITIALIZER; | |
| 302 | |
| 303 } // namespace chrome_browser_metrics | 299 } // namespace chrome_browser_metrics |
| OLD | NEW |