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

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

Issue 2449143002: Actually update FieldTrialEntry's activated field (Closed)
Patch Set: fix locking problem 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') | no next file » | 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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « base/metrics/field_trial.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698