Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: base/metrics/field_trial.cc

Issue 2453933004: Fix deadlock issue with AllStatesToString (Closed)
Patch Set: fix nit Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/metrics/field_trial.h ('k') | base/metrics/field_trial_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/metrics/field_trial.h" 5 #include "base/metrics/field_trial.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/base_switches.h" 10 #include "base/base_switches.h"
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { 330 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) {
331 group_ = number; 331 group_ = number;
332 if (group_name.empty()) 332 if (group_name.empty())
333 StringAppendF(&group_name_, "%d", group_); 333 StringAppendF(&group_name_, "%d", group_);
334 else 334 else
335 group_name_ = group_name; 335 group_name_ = group_name;
336 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; 336 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_;
337 } 337 }
338 338
339 void FieldTrial::FinalizeGroupChoice() { 339 void FieldTrial::FinalizeGroupChoice() {
340 FinalizeGroupChoiceImpl(false);
341 }
342
343 void FieldTrial::FinalizeGroupChoiceImpl(bool is_locked) {
340 if (group_ != kNotFinalized) 344 if (group_ != kNotFinalized)
341 return; 345 return;
342 accumulated_group_probability_ = divisor_; 346 accumulated_group_probability_ = divisor_;
343 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not 347 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not
344 // finalized. 348 // finalized.
345 DCHECK(!forced_); 349 DCHECK(!forced_);
346 SetGroupChoice(default_group_name_, kDefaultGroupNumber); 350 SetGroupChoice(default_group_name_, kDefaultGroupNumber);
347 351
348 // Add the field trial to shared memory. 352 // Add the field trial to shared memory.
349 if (kUseSharedMemoryForFieldTrials) 353 if (kUseSharedMemoryForFieldTrials)
350 FieldTrialList::OnGroupFinalized(this); 354 FieldTrialList::OnGroupFinalized(is_locked, this);
351 } 355 }
352 356
353 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { 357 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const {
354 if (!group_reported_ || !enable_field_trial_) 358 if (!group_reported_ || !enable_field_trial_)
355 return false; 359 return false;
356 DCHECK_NE(group_, kNotFinalized); 360 DCHECK_NE(group_, kNotFinalized);
357 active_group->trial_name = trial_name_; 361 active_group->trial_name = trial_name_;
358 active_group->group_name = group_name_; 362 active_group->group_name = group_name_;
359 return true; 363 return true;
360 } 364 }
361 365
362 bool FieldTrial::GetState(State* field_trial_state) { 366 bool FieldTrial::GetState(State* field_trial_state) {
363 if (!enable_field_trial_) 367 if (!enable_field_trial_)
364 return false; 368 return false;
365 FinalizeGroupChoice(); 369 FinalizeGroupChoice();
366 field_trial_state->trial_name = trial_name_; 370 field_trial_state->trial_name = trial_name_;
367 field_trial_state->group_name = group_name_; 371 field_trial_state->group_name = group_name_;
368 field_trial_state->activated = group_reported_; 372 field_trial_state->activated = group_reported_;
369 return true; 373 return true;
370 } 374 }
371 375
376 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) {
377 if (!enable_field_trial_)
378 return false;
379 FinalizeGroupChoiceImpl(true);
380 field_trial_state->trial_name = trial_name_;
381 field_trial_state->group_name = group_name_;
382 field_trial_state->activated = group_reported_;
383 return true;
384 }
385
372 //------------------------------------------------------------------------------ 386 //------------------------------------------------------------------------------
373 // FieldTrialList methods and members. 387 // FieldTrialList methods and members.
374 388
375 // static 389 // static
376 FieldTrialList* FieldTrialList::global_ = NULL; 390 FieldTrialList* FieldTrialList::global_ = NULL;
377 391
378 // static 392 // static
379 bool FieldTrialList::used_without_global_ = false; 393 bool FieldTrialList::used_without_global_ = false;
380 394
381 FieldTrialList::Observer::~Observer() { 395 FieldTrialList::Observer::~Observer() {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 } 556 }
543 557
544 // static 558 // static
545 void FieldTrialList::AllStatesToString(std::string* output) { 559 void FieldTrialList::AllStatesToString(std::string* output) {
546 if (!global_) 560 if (!global_)
547 return; 561 return;
548 AutoLock auto_lock(global_->lock_); 562 AutoLock auto_lock(global_->lock_);
549 563
550 for (const auto& registered : global_->registered_) { 564 for (const auto& registered : global_->registered_) {
551 FieldTrial::State trial; 565 FieldTrial::State trial;
552 if (!registered.second->GetState(&trial)) 566 if (!registered.second->GetStateWhileLocked(&trial))
553 continue; 567 continue;
554 DCHECK_EQ(std::string::npos, 568 DCHECK_EQ(std::string::npos,
555 trial.trial_name.find(kPersistentStringSeparator)); 569 trial.trial_name.find(kPersistentStringSeparator));
556 DCHECK_EQ(std::string::npos, 570 DCHECK_EQ(std::string::npos,
557 trial.group_name.find(kPersistentStringSeparator)); 571 trial.group_name.find(kPersistentStringSeparator));
558 if (trial.activated) 572 if (trial.activated)
559 output->append(1, kActivationMarker); 573 output->append(1, kActivationMarker);
560 trial.trial_name.AppendToString(output); 574 trial.trial_name.AppendToString(output);
561 output->append(1, kPersistentStringSeparator); 575 output->append(1, kPersistentStringSeparator);
562 trial.group_name.AppendToString(output); 576 trial.group_name.AppendToString(output);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 if (global_->readonly_allocator_handle_) 691 if (global_->readonly_allocator_handle_)
678 handles->push_back(global_->readonly_allocator_handle_); 692 handles->push_back(global_->readonly_allocator_handle_);
679 } 693 }
680 } 694 }
681 #endif 695 #endif
682 696
683 // static 697 // static
684 void FieldTrialList::CopyFieldTrialStateToFlags( 698 void FieldTrialList::CopyFieldTrialStateToFlags(
685 const char* field_trial_handle_switch, 699 const char* field_trial_handle_switch,
686 CommandLine* cmd_line) { 700 CommandLine* cmd_line) {
701 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However,
702 // content browser tests currently don't create a FieldTrialList because they
703 // don't run ChromeBrowserMainParts code where it's done for Chrome.
704 if (!global_)
705 return;
706
687 #if defined(OS_WIN) 707 #if defined(OS_WIN)
688 // Use shared memory to pass the state if the feature is enabled, otherwise 708 // Use shared memory to pass the state if the feature is enabled, otherwise
689 // fallback to passing it via the command line as a string. 709 // fallback to passing it via the command line as a string.
690 if (kUseSharedMemoryForFieldTrials) { 710 if (kUseSharedMemoryForFieldTrials) {
691 InstantiateFieldTrialAllocatorIfNeeded(); 711 InstantiateFieldTrialAllocatorIfNeeded();
692 // If the readonly handle didn't get duplicated properly, then fallback to 712 // If the readonly handle didn't get duplicated properly, then fallback to
693 // original behavior. 713 // original behavior.
694 if (!global_->readonly_allocator_handle_) { 714 if (!global_->readonly_allocator_handle_) {
695 AddForceFieldTrialsFlag(cmd_line); 715 AddForceFieldTrialsFlag(cmd_line);
696 return; 716 return;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 } 771 }
752 772
753 // static 773 // static
754 void FieldTrialList::RemoveObserver(Observer* observer) { 774 void FieldTrialList::RemoveObserver(Observer* observer) {
755 if (!global_) 775 if (!global_)
756 return; 776 return;
757 global_->observer_list_->RemoveObserver(observer); 777 global_->observer_list_->RemoveObserver(observer);
758 } 778 }
759 779
760 // static 780 // static
761 void FieldTrialList::OnGroupFinalized(FieldTrial* field_trial) { 781 void FieldTrialList::OnGroupFinalized(bool is_locked, FieldTrial* field_trial) {
762 if (!global_) 782 if (!global_)
763 return; 783 return;
764 AutoLock auto_lock(global_->lock_); 784 if (is_locked) {
765 AddToAllocatorWhileLocked(field_trial); 785 AddToAllocatorWhileLocked(field_trial);
786 } else {
787 AutoLock auto_lock(global_->lock_);
788 AddToAllocatorWhileLocked(field_trial);
789 }
766 } 790 }
767 791
768 // static 792 // static
769 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { 793 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) {
770 if (!global_) 794 if (!global_)
771 return; 795 return;
772 796
773 { 797 {
774 AutoLock auto_lock(global_->lock_); 798 AutoLock auto_lock(global_->lock_);
775 if (field_trial->group_reported_) 799 if (field_trial->group_reported_)
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
948 return; 972 return;
949 } 973 }
950 AutoLock auto_lock(global_->lock_); 974 AutoLock auto_lock(global_->lock_);
951 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 975 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
952 trial->AddRef(); 976 trial->AddRef();
953 trial->SetTrialRegistered(); 977 trial->SetTrialRegistered();
954 global_->registered_[trial->trial_name()] = trial; 978 global_->registered_[trial->trial_name()] = trial;
955 } 979 }
956 980
957 } // namespace base 981 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/field_trial.h ('k') | base/metrics/field_trial_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698