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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 : trial_name_(trial_name), | 302 : trial_name_(trial_name), |
303 divisor_(total_probability), | 303 divisor_(total_probability), |
304 default_group_name_(default_group_name), | 304 default_group_name_(default_group_name), |
305 random_(GetGroupBoundaryValue(total_probability, entropy_value)), | 305 random_(GetGroupBoundaryValue(total_probability, entropy_value)), |
306 accumulated_group_probability_(0), | 306 accumulated_group_probability_(0), |
307 next_group_number_(kDefaultGroupNumber + 1), | 307 next_group_number_(kDefaultGroupNumber + 1), |
308 group_(kNotFinalized), | 308 group_(kNotFinalized), |
309 enable_field_trial_(true), | 309 enable_field_trial_(true), |
310 forced_(false), | 310 forced_(false), |
311 group_reported_(false), | 311 group_reported_(false), |
312 trial_registered_(false) { | 312 trial_registered_(false), |
313 ref_(SharedPersistentMemoryAllocator::kReferenceNull) { | |
313 DCHECK_GT(total_probability, 0); | 314 DCHECK_GT(total_probability, 0); |
314 DCHECK(!trial_name_.empty()); | 315 DCHECK(!trial_name_.empty()); |
315 DCHECK(!default_group_name_.empty()); | 316 DCHECK(!default_group_name_.empty()); |
316 } | 317 } |
317 | 318 |
318 FieldTrial::~FieldTrial() {} | 319 FieldTrial::~FieldTrial() {} |
319 | 320 |
320 void FieldTrial::SetTrialRegistered() { | 321 void FieldTrial::SetTrialRegistered() { |
321 DCHECK_EQ(kNotFinalized, group_); | 322 DCHECK_EQ(kNotFinalized, group_); |
322 DCHECK(!trial_registered_); | 323 DCHECK(!trial_registered_); |
(...skipping 10 matching lines...) Expand all Loading... | |
333 } | 334 } |
334 | 335 |
335 void FieldTrial::FinalizeGroupChoice() { | 336 void FieldTrial::FinalizeGroupChoice() { |
336 if (group_ != kNotFinalized) | 337 if (group_ != kNotFinalized) |
337 return; | 338 return; |
338 accumulated_group_probability_ = divisor_; | 339 accumulated_group_probability_ = divisor_; |
339 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not | 340 // Here it's OK to use |kDefaultGroupNumber| since we can't be forced and not |
340 // finalized. | 341 // finalized. |
341 DCHECK(!forced_); | 342 DCHECK(!forced_); |
342 SetGroupChoice(default_group_name_, kDefaultGroupNumber); | 343 SetGroupChoice(default_group_name_, kDefaultGroupNumber); |
344 | |
345 // Add the field trial to shared memory. | |
346 if (kUseSharedMemoryForFieldTrials) | |
347 FieldTrialList::OnGroupFinalized(this); | |
343 } | 348 } |
344 | 349 |
345 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { | 350 bool FieldTrial::GetActiveGroup(ActiveGroup* active_group) const { |
346 if (!group_reported_ || !enable_field_trial_) | 351 if (!group_reported_ || !enable_field_trial_) |
347 return false; | 352 return false; |
348 DCHECK_NE(group_, kNotFinalized); | 353 DCHECK_NE(group_, kNotFinalized); |
349 active_group->trial_name = trial_name_; | 354 active_group->trial_name = trial_name_; |
350 active_group->group_name = group_name_; | 355 active_group->group_name = group_name_; |
351 return true; | 356 return true; |
352 } | 357 } |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
765 } | 770 } |
766 | 771 |
767 // static | 772 // static |
768 void FieldTrialList::RemoveObserver(Observer* observer) { | 773 void FieldTrialList::RemoveObserver(Observer* observer) { |
769 if (!global_) | 774 if (!global_) |
770 return; | 775 return; |
771 global_->observer_list_->RemoveObserver(observer); | 776 global_->observer_list_->RemoveObserver(observer); |
772 } | 777 } |
773 | 778 |
774 // static | 779 // static |
780 void FieldTrialList::OnGroupFinalized(FieldTrial* field_trial) { | |
781 if (!global_) | |
782 return; | |
783 AutoLock auto_lock(global_->lock_); | |
784 AddToAllocatorWhileLocked(field_trial); | |
785 } | |
786 | |
787 // static | |
775 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { | 788 void FieldTrialList::NotifyFieldTrialGroupSelection(FieldTrial* field_trial) { |
776 if (!global_) | 789 if (!global_) |
777 return; | 790 return; |
778 | 791 |
779 { | 792 { |
780 AutoLock auto_lock(global_->lock_); | 793 AutoLock auto_lock(global_->lock_); |
781 if (field_trial->group_reported_) | 794 if (field_trial->group_reported_) |
782 return; | 795 return; |
783 field_trial->group_reported_ = true; | 796 field_trial->group_reported_ = true; |
784 | 797 |
785 if (!field_trial->enable_field_trial_) | 798 if (!field_trial->enable_field_trial_) |
786 return; | 799 return; |
787 | 800 |
788 if (kUseSharedMemoryForFieldTrials) { | 801 if (kUseSharedMemoryForFieldTrials) |
789 field_trial->AddToAllocatorWhileLocked( | 802 ActivateFieldTrialEntry(field_trial); |
790 global_->field_trial_allocator_.get()); | |
791 } | |
792 } | 803 } |
793 | 804 |
794 global_->observer_list_->Notify( | 805 global_->observer_list_->Notify( |
795 FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized, | 806 FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized, |
796 field_trial->trial_name(), field_trial->group_name_internal()); | 807 field_trial->trial_name(), field_trial->group_name_internal()); |
797 } | 808 } |
798 | 809 |
810 // static | |
811 void FieldTrialList::ActivateFieldTrialEntry(FieldTrial* field_trial) { | |
Alexei Svitkine (slow)
2016/10/26 16:21:08
Nit: Please order the functions the same way as in
lawrencewu
2016/10/26 16:35:24
Done.
| |
812 SharedPersistentMemoryAllocator* allocator = | |
813 global_->field_trial_allocator_.get(); | |
814 SharedPersistentMemoryAllocator::Reference ref = field_trial->ref_; | |
815 if (ref == SharedPersistentMemoryAllocator::kReferenceNull) { | |
816 // It's fine to do this even if the allocator hasn't been instantiated | |
817 // yet -- it'll just return early. | |
818 AddToAllocatorWhileLocked(field_trial); | |
819 } else { | |
820 // It's also okay to do this even though the callee doesn't have a lock -- | |
821 // the only thing that happens on a stale read here is a slight performance | |
822 // hit from the child re-synchronizing activation state. | |
823 FieldTrialEntry* entry = | |
824 allocator->GetAsObject<FieldTrialEntry>(ref, kFieldTrialType); | |
825 entry->activated = true; | |
826 } | |
827 } | |
828 | |
799 #if !defined(OS_NACL) | 829 #if !defined(OS_NACL) |
800 // static | 830 // static |
801 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() { | 831 void FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded() { |
802 AutoLock auto_lock(global_->lock_); | 832 if (!global_) |
803 // Create the allocator if not already created and add all existing trials. | |
804 if (global_->field_trial_allocator_ != nullptr) | |
805 return; | 833 return; |
834 { | |
Alexei Svitkine (slow)
2016/10/26 16:21:08
Nit: No need for this block since the auto_lock ap
lawrencewu
2016/10/26 16:35:24
Fixed.
| |
835 AutoLock auto_lock(global_->lock_); | |
836 // Create the allocator if not already created and add all existing trials. | |
837 if (global_->field_trial_allocator_ != nullptr) | |
838 return; | |
806 | 839 |
807 std::unique_ptr<SharedMemory> shm(new SharedMemory()); | 840 std::unique_ptr<SharedMemory> shm(new SharedMemory()); |
808 if (!shm->CreateAndMapAnonymous(kFieldTrialAllocationSize)) | 841 if (!shm->CreateAndMapAnonymous(kFieldTrialAllocationSize)) |
809 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); | 842 TerminateBecauseOutOfMemory(kFieldTrialAllocationSize); |
810 | 843 |
811 // TODO(lawrencewu): call UpdateTrackingHistograms() when all field trials | 844 // TODO(lawrencewu): call UpdateTrackingHistograms() when all field trials |
812 // have been registered (perhaps in the destructor?) | 845 // have been registered (perhaps in the destructor?) |
813 global_->field_trial_allocator_.reset(new SharedPersistentMemoryAllocator( | 846 global_->field_trial_allocator_.reset(new SharedPersistentMemoryAllocator( |
814 std::move(shm), 0, kAllocatorName, false)); | 847 std::move(shm), 0, kAllocatorName, false)); |
815 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); | 848 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); |
816 | 849 |
817 // Add all existing field trials. | 850 // Add all existing field trials. |
818 for (const auto& registered : global_->registered_) { | 851 for (const auto& registered : global_->registered_) { |
819 registered.second->AddToAllocatorWhileLocked( | 852 AddToAllocatorWhileLocked(registered.second); |
820 global_->field_trial_allocator_.get()); | 853 } |
821 } | |
822 | 854 |
823 #if defined(OS_WIN) | 855 #if defined(OS_WIN) |
824 // Set |readonly_allocator_handle_| so we can pass it to be inherited and via | 856 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
825 // the command line. | 857 // via the command line. |
826 global_->readonly_allocator_handle_ = | 858 global_->readonly_allocator_handle_ = |
827 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 859 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); |
828 #endif | 860 #endif |
861 } | |
829 } | 862 } |
830 #endif | 863 #endif |
831 | 864 |
832 void FieldTrial::AddToAllocatorWhileLocked( | 865 // static |
833 SharedPersistentMemoryAllocator* allocator) { | 866 size_t FieldTrialList::GetFieldTrialCount() { |
867 if (!global_) | |
868 return 0; | |
869 AutoLock auto_lock(global_->lock_); | |
870 return global_->registered_.size(); | |
871 } | |
872 | |
873 // static | |
874 void FieldTrialList::AddToAllocatorWhileLocked(FieldTrial* field_trial) { | |
875 SharedPersistentMemoryAllocator* allocator = | |
876 global_->field_trial_allocator_.get(); | |
877 | |
834 // Don't do anything if the allocator hasn't been instantiated yet. | 878 // Don't do anything if the allocator hasn't been instantiated yet. |
835 if (allocator == nullptr) | 879 if (allocator == nullptr) |
836 return; | 880 return; |
837 | 881 |
838 State trial_state; | 882 // Or if we've already added it. |
839 if (!GetState(&trial_state)) | 883 if (field_trial->ref_ != SharedPersistentMemoryAllocator::kReferenceNull) |
884 return; | |
885 | |
886 FieldTrial::State trial_state; | |
887 if (!field_trial->GetState(&trial_state)) | |
840 return; | 888 return; |
841 | 889 |
842 size_t trial_name_size = trial_state.trial_name.size() + 1; | 890 size_t trial_name_size = trial_state.trial_name.size() + 1; |
843 size_t group_name_size = trial_state.group_name.size() + 1; | 891 size_t group_name_size = trial_state.group_name.size() + 1; |
844 size_t size = sizeof(FieldTrialEntry) + trial_name_size + group_name_size; | 892 size_t size = sizeof(FieldTrialEntry) + trial_name_size + group_name_size; |
845 | 893 |
846 // Allocate just enough memory to fit the FieldTrialEntry struct, trial name, | 894 // Allocate just enough memory to fit the FieldTrialEntry struct, trial name, |
847 // and group name. | 895 // and group name. |
848 SharedPersistentMemoryAllocator::Reference ref = | 896 SharedPersistentMemoryAllocator::Reference ref = |
849 allocator->Allocate(size, kFieldTrialType); | 897 allocator->Allocate(size, kFieldTrialType); |
(...skipping 12 matching lines...) Expand all Loading... | |
862 char* trial_name = reinterpret_cast<char*>(entry) + trial_name_offset; | 910 char* trial_name = reinterpret_cast<char*>(entry) + trial_name_offset; |
863 char* group_name = reinterpret_cast<char*>(entry) + group_name_offset; | 911 char* group_name = reinterpret_cast<char*>(entry) + group_name_offset; |
864 memcpy(trial_name, trial_state.trial_name.data(), trial_name_size); | 912 memcpy(trial_name, trial_state.trial_name.data(), trial_name_size); |
865 memcpy(group_name, trial_state.group_name.data(), group_name_size); | 913 memcpy(group_name, trial_state.group_name.data(), group_name_size); |
866 | 914 |
867 // Null terminate the strings. | 915 // Null terminate the strings. |
868 trial_name[trial_state.trial_name.size()] = '\0'; | 916 trial_name[trial_state.trial_name.size()] = '\0'; |
869 group_name[trial_state.group_name.size()] = '\0'; | 917 group_name[trial_state.group_name.size()] = '\0'; |
870 | 918 |
871 allocator->MakeIterable(ref); | 919 allocator->MakeIterable(ref); |
920 field_trial->ref_ = ref; | |
872 } | 921 } |
873 | 922 |
874 // static | 923 // static |
875 size_t FieldTrialList::GetFieldTrialCount() { | |
876 if (!global_) | |
877 return 0; | |
878 AutoLock auto_lock(global_->lock_); | |
879 return global_->registered_.size(); | |
880 } | |
881 | |
882 // static | |
883 const FieldTrial::EntropyProvider* | 924 const FieldTrial::EntropyProvider* |
884 FieldTrialList::GetEntropyProviderForOneTimeRandomization() { | 925 FieldTrialList::GetEntropyProviderForOneTimeRandomization() { |
885 if (!global_) { | 926 if (!global_) { |
886 used_without_global_ = true; | 927 used_without_global_ = true; |
887 return NULL; | 928 return NULL; |
888 } | 929 } |
889 | 930 |
890 return global_->entropy_provider_.get(); | 931 return global_->entropy_provider_.get(); |
891 } | 932 } |
892 | 933 |
(...skipping 11 matching lines...) Expand all Loading... | |
904 return; | 945 return; |
905 } | 946 } |
906 AutoLock auto_lock(global_->lock_); | 947 AutoLock auto_lock(global_->lock_); |
907 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 948 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
908 trial->AddRef(); | 949 trial->AddRef(); |
909 trial->SetTrialRegistered(); | 950 trial->SetTrialRegistered(); |
910 global_->registered_[trial->trial_name()] = trial; | 951 global_->registered_[trial->trial_name()] = trial; |
911 } | 952 } |
912 | 953 |
913 } // namespace base | 954 } // namespace base |
OLD | NEW |