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 "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 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
327 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { | 327 void FieldTrial::SetGroupChoice(const std::string& group_name, int number) { |
328 group_ = number; | 328 group_ = number; |
329 if (group_name.empty()) | 329 if (group_name.empty()) |
330 StringAppendF(&group_name_, "%d", group_); | 330 StringAppendF(&group_name_, "%d", group_); |
331 else | 331 else |
332 group_name_ = group_name; | 332 group_name_ = group_name; |
333 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; | 333 DVLOG(1) << "Field trial: " << trial_name_ << " Group choice:" << group_name_; |
334 } | 334 } |
335 | 335 |
336 void FieldTrial::FinalizeGroupChoice() { | 336 void FieldTrial::FinalizeGroupChoice() { |
337 FinalizeGroupChoiceImpl(false); | |
338 } | |
339 | |
340 void FieldTrial::FinalizeGroupChoiceImpl(bool is_locked) { | |
337 if (group_ != kNotFinalized) | 341 if (group_ != kNotFinalized) |
338 return; | 342 return; |
339 accumulated_group_probability_ = divisor_; | 343 accumulated_group_probability_ = divisor_; |
340 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not | 344 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not |
341 // finalized. | 345 // finalized. |
342 DCHECK(!forced_); | 346 DCHECK(!forced_); |
343 SetGroupChoice(default_group_name_, kDefaultGroupNumber); | 347 SetGroupChoice(default_group_name_, kDefaultGroupNumber); |
344 | 348 |
345 // Add the field trial to shared memory. | 349 // Add the field trial to shared memory. |
346 if (kUseSharedMemoryForFieldTrials) | 350 if (kUseSharedMemoryForFieldTrials) |
347 FieldTrialList::OnGroupFinalized(this); | 351 FieldTrialList::OnGroupFinalized(is_locked, this); |
348 } | 352 } |
349 | 353 |
350 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { | 354 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { |
351 if (!group_reported_ || !enable_field_trial_) | 355 if (!group_reported_ || !enable_field_trial_) |
352 return false; | 356 return false; |
353 DCHECK_NE(group_, kNotFinalized); | 357 DCHECK_NE(group_, kNotFinalized); |
354 active_group->trial_name = trial_name_; | 358 active_group->trial_name = trial_name_; |
355 active_group->group_name = group_name_; | 359 active_group->group_name = group_name_; |
356 return true; | 360 return true; |
357 } | 361 } |
358 | 362 |
359 bool FieldTrial::GetState(State* field_trial_state) { | 363 bool FieldTrial::GetState(State* field_trial_state) { |
360 if (!enable_field_trial_) | 364 if (!enable_field_trial_) |
361 return false; | 365 return false; |
362 FinalizeGroupChoice(); | 366 FinalizeGroupChoice(); |
363 field_trial_state->trial_name = trial_name_; | 367 field_trial_state->trial_name = trial_name_; |
364 field_trial_state->group_name = group_name_; | 368 field_trial_state->group_name = group_name_; |
365 field_trial_state->activated = group_reported_; | 369 field_trial_state->activated = group_reported_; |
366 return true; | 370 return true; |
367 } | 371 } |
368 | 372 |
373 bool FieldTrial::GetStateWhileLocked(State* field_trial_state) { | |
374 if (!enable_field_trial_) | |
375 return false; | |
376 FinalizeGroupChoiceImpl(true); | |
377 field_trial_state->trial_name = trial_name_; | |
378 field_trial_state->group_name = group_name_; | |
379 field_trial_state->activated = group_reported_; | |
380 return true; | |
381 } | |
382 | |
369 //------------------------------------------------------------------------------ | 383 //------------------------------------------------------------------------------ |
370 // FieldTrialList methods and members. | 384 // FieldTrialList methods and members. |
371 | 385 |
372 // static | 386 // static |
373 FieldTrialList* FieldTrialList::global_ = NULL; | 387 FieldTrialList* FieldTrialList::global_ = NULL; |
374 | 388 |
375 // static | 389 // static |
376 bool FieldTrialList::used_without_global_ = false; | 390 bool FieldTrialList::used_without_global_ = false; |
377 | 391 |
378 FieldTrialList::Observer::~Observer() { | 392 FieldTrialList::Observer::~Observer() { |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
539 } | 553 } |
540 | 554 |
541 // static | 555 // static |
542 void FieldTrialList::AllStatesToString(std::string* output) { | 556 void FieldTrialList::AllStatesToString(std::string* output) { |
543 if (!global_) | 557 if (!global_) |
544 return; | 558 return; |
545 AutoLock auto_lock(global_->lock_); | 559 AutoLock auto_lock(global_->lock_); |
546 | 560 |
547 for (const auto& registered : global_->registered_) { | 561 for (const auto& registered : global_->registered_) { |
548 FieldTrial::State trial; | 562 FieldTrial::State trial; |
549 if (!registered.second->GetState(&trial)) | 563 if (!registered.second->GetStateWhileLocked(&trial)) |
550 continue; | 564 continue; |
551 DCHECK_EQ(std::string::npos, | 565 DCHECK_EQ(std::string::npos, |
552 trial.trial_name.find(kPersistentStringSeparator)); | 566 trial.trial_name.find(kPersistentStringSeparator)); |
553 DCHECK_EQ(std::string::npos, | 567 DCHECK_EQ(std::string::npos, |
554 trial.group_name.find(kPersistentStringSeparator)); | 568 trial.group_name.find(kPersistentStringSeparator)); |
555 if (trial.activated) | 569 if (trial.activated) |
556 output->append(1, kActivationMarker); | 570 output->append(1, kActivationMarker); |
557 trial.trial_name.AppendToString(output); | 571 trial.trial_name.AppendToString(output); |
558 output->append(1, kPersistentStringSeparator); | 572 output->append(1, kPersistentStringSeparator); |
559 trial.group_name.AppendToString(output); | 573 trial.group_name.AppendToString(output); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
664 } | 678 } |
665 | 679 |
666 #if defined(OS_WIN) | 680 #if defined(OS_WIN) |
667 // static | 681 // static |
668 void FieldTrialList::AppendFieldTrialHandleIfNeeded( | 682 void FieldTrialList::AppendFieldTrialHandleIfNeeded( |
669 HandlesToInheritVector* handles) { | 683 HandlesToInheritVector* handles) { |
670 if (!global_) | 684 if (!global_) |
671 return; | 685 return; |
672 if (kUseSharedMemoryForFieldTrials) { | 686 if (kUseSharedMemoryForFieldTrials) { |
673 InstantiateFieldTrialAllocatorIfNeeded(); | 687 InstantiateFieldTrialAllocatorIfNeeded(); |
674 if (global_->readonly_allocator_handle_) | 688 if (global_ && global_->readonly_allocator_handle_) |
Alexei Svitkine (slow)
2016/10/28 18:57:34
There's already an early return on line 684.
lawrencewu
2016/10/31 18:59:25
Fixed.
| |
675 handles->push_back(global_->readonly_allocator_handle_); | 689 handles->push_back(global_->readonly_allocator_handle_); |
676 } | 690 } |
677 } | 691 } |
678 #endif | 692 #endif |
679 | 693 |
680 // static | 694 // static |
681 void FieldTrialList::CopyFieldTrialStateToFlags( | 695 void FieldTrialList::CopyFieldTrialStateToFlags( |
682 const char* field_trial_handle_switch, | 696 const char* field_trial_handle_switch, |
683 CommandLine* cmd_line) { | 697 CommandLine* cmd_line) { |
684 #if defined(OS_WIN) | 698 #if defined(OS_WIN) |
685 // Use shared memory to pass the state if the feature is enabled, otherwise | 699 // Use shared memory to pass the state if the feature is enabled, otherwise |
686 // fallback to passing it via the command line as a string. | 700 // fallback to passing it via the command line as a string. |
687 if (kUseSharedMemoryForFieldTrials) { | 701 if (kUseSharedMemoryForFieldTrials) { |
688 InstantiateFieldTrialAllocatorIfNeeded(); | 702 InstantiateFieldTrialAllocatorIfNeeded(); |
689 // If the readonly handle didn't get duplicated properly, then fallback to | 703 // If the readonly handle didn't get duplicated properly, then fallback to |
690 // original behavior. | 704 // original behavior. |
691 if (!global_->readonly_allocator_handle_) { | 705 if (!global_ || !global_->readonly_allocator_handle_) { |
Alexei Svitkine (slow)
2016/10/28 18:57:34
Can we instead fix the browser test to have a Fiel
lawrencewu
2016/10/31 18:59:25
As we discussed, I moved the check for global to t
| |
692 AddForceFieldTrialsFlag(cmd_line); | 706 AddForceFieldTrialsFlag(cmd_line); |
693 return; | 707 return; |
694 } | 708 } |
695 | 709 |
696 // HANDLE is just typedef'd to void *. We basically cast the handle into an | 710 // HANDLE is just typedef'd to void *. We basically cast the handle into an |
697 // int (uintptr_t, to be exact), stringify the int, and pass it as a | 711 // int (uintptr_t, to be exact), stringify the int, and pass it as a |
698 // command-line flag. The child process will do the reverse conversions to | 712 // command-line flag. The child process will do the reverse conversions to |
699 // retrieve the handle. See http://stackoverflow.com/a/153077 | 713 // retrieve the handle. See http://stackoverflow.com/a/153077 |
700 auto uintptr_handle = | 714 auto uintptr_handle = |
701 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); | 715 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
748 } | 762 } |
749 | 763 |
750 // static | 764 // static |
751 void FieldTrialList::RemoveObserver(Observer* observer) { | 765 void FieldTrialList::RemoveObserver(Observer* observer) { |
752 if (!global_) | 766 if (!global_) |
753 return; | 767 return; |
754 global_->observer_list_->RemoveObserver(observer); | 768 global_->observer_list_->RemoveObserver(observer); |
755 } | 769 } |
756 | 770 |
757 // static | 771 // static |
758 void FieldTrialList::OnGroupFinalized(FieldTrial* field_trial) { | 772 void FieldTrialList::OnGroupFinalized(bool is_locked, FieldTrial* field_trial) { |
759 if (!global_) | 773 if (!global_) |
760 return; | 774 return; |
761 AutoLock auto_lock(global_->lock_); | 775 if (is_locked) { |
762 AddToAllocatorWhileLocked(field_trial); | 776 AddToAllocatorWhileLocked(field_trial); |
777 } else { | |
778 AutoLock auto_lock(global_->lock_); | |
779 AddToAllocatorWhileLocked(field_trial); | |
780 } | |
763 } | 781 } |
764 | 782 |
765 // static | 783 // static |
766 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { | 784 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { |
767 if (!global_) | 785 if (!global_) |
768 return; | 786 return; |
769 | 787 |
770 { | 788 { |
771 AutoLock auto_lock(global_->lock_); | 789 AutoLock auto_lock(global_->lock_); |
772 if (field_trial->group_reported_) | 790 if (field_trial->group_reported_) |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
944 return; | 962 return; |
945 } | 963 } |
946 AutoLock auto_lock(global_->lock_); | 964 AutoLock auto_lock(global_->lock_); |
947 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 965 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
948 trial->AddRef(); | 966 trial->AddRef(); |
949 trial->SetTrialRegistered(); | 967 trial->SetTrialRegistered(); |
950 global_->registered_[trial->trial_name()] = trial; | 968 global_->registered_[trial->trial_name()] = trial; |
951 } | 969 } |
952 | 970 |
953 } // namespace base | 971 } // namespace base |
OLD | NEW |