Index: chrome/common/metrics/experiments_helper.cc |
diff --git a/chrome/common/metrics/experiments_helper.cc b/chrome/common/metrics/experiments_helper.cc |
index 09e41cc362e3375dd1f2e8ad03fae64c09e4a095..11c7c1389fca180304be1513a6498446e06d441e 100644 |
--- a/chrome/common/metrics/experiments_helper.cc |
+++ b/chrome/common/metrics/experiments_helper.cc |
@@ -6,13 +6,79 @@ |
#include <vector> |
-#include "base/metrics/field_trial.h" |
+#include "base/memory/singleton.h" |
#include "base/string16.h" |
#include "base/stringprintf.h" |
#include "base/utf_string_conversions.h" |
#include "chrome/common/child_process_logging.h" |
-namespace ExperimentsHelper { |
+namespace { |
+ |
+// We need to pass a Compare class to the std::map template since NameGroupId |
+// is a user-defined type. |
+struct NameGroupIdCompare { |
+ bool operator() (const base::FieldTrial::NameGroupId& lhs, |
+ const base::FieldTrial::NameGroupId& rhs) const { |
+ // The group and name fields are just SHA-1 Hashes, so we just need to treat |
+ // them as IDs and do a less-than comparison. We test group first, since |
+ // name is more likely to collide. |
+ return lhs.group == rhs.group ? lhs.name < rhs.name : |
+ lhs.group < rhs.group; |
+ } |
+}; |
+ |
+// The internal singleton accessor for the map, used to keep it thread-safe. |
+class GroupMapAccessor { |
+ public: |
+ // Retrieve the singleton. |
+ static GroupMapAccessor* GetInstance() { |
+ return Singleton<GroupMapAccessor>::get(); |
+ } |
+ |
+ GroupMapAccessor() {} |
+ ~GroupMapAccessor() {} |
+ |
+ void AssociateID(const base::FieldTrial::NameGroupId& group_identifier, |
+ experiments_helper::GoogleExperimentID id) { |
+ base::AutoLock scoped_lock(lock_); |
+ DCHECK(group_to_id_map_.find(group_identifier) == group_to_id_map_.end()) << |
+ "You can associate a group with a GoogleExperimentID only once."; |
+ group_to_id_map_[group_identifier] = id; |
+ } |
+ |
+ experiments_helper::GoogleExperimentID GetID( |
+ const base::FieldTrial::NameGroupId& group_identifier) { |
+ base::AutoLock scoped_lock(lock_); |
+ GroupToIDMap::const_iterator it = group_to_id_map_.find(group_identifier); |
+ if (it == group_to_id_map_.end()) |
+ return experiments_helper::kEmptyGoogleExperimentID; |
+ return it->second; |
+ } |
+ |
+ private: |
+ typedef std::map<base::FieldTrial::NameGroupId, |
+ experiments_helper::GoogleExperimentID, NameGroupIdCompare> GroupToIDMap; |
+ |
+ base::Lock lock_; |
+ GroupToIDMap group_to_id_map_; |
+}; |
+ |
+} // namespace |
+ |
+namespace experiments_helper { |
+ |
+const GoogleExperimentID kEmptyGoogleExperimentID = 0; |
+ |
+void AssociateGoogleExperimentID( |
+ const base::FieldTrial::NameGroupId& group_identifier, |
+ GoogleExperimentID id) { |
+ GroupMapAccessor::GetInstance()->AssociateID(group_identifier, id); |
+} |
+ |
+GoogleExperimentID GetGoogleExperimentID( |
+ const base::FieldTrial::NameGroupId& group_identifier) { |
+ return GroupMapAccessor::GetInstance()->GetID(group_identifier); |
+} |
void SetChildProcessLoggingExperimentList() { |
std::vector<base::FieldTrial::NameGroupId> name_group_ids; |
@@ -26,4 +92,4 @@ void SetChildProcessLoggingExperimentList() { |
child_process_logging::SetExperimentList(experiment_strings); |
} |
-} // namespace ExperimentsHelper |
+} // namespace experiments_helper |