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

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

Issue 5784005: Properly lock access to static variables.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years 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 | Annotate | Revision Log
« no previous file with comments | « base/metrics/histogram.h ('k') | chrome/renderer/renderer_main.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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 // Histogram is an object that aggregates statistics, and can summarize them in 5 // Histogram is an object that aggregates statistics, and can summarize them in
6 // various forms, including ASCII graphical, HTML, and numerically (as a 6 // various forms, including ASCII graphical, HTML, and numerically (as a
7 // vector of numbers corresponding to each of the aggregating buckets). 7 // vector of numbers corresponding to each of the aggregating buckets).
8 // See header file for details and examples. 8 // See header file for details and examples.
9 9
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 //------------------------------------------------------------------------------ 897 //------------------------------------------------------------------------------
898 // The next section handles global (central) support for all histograms, as well 898 // The next section handles global (central) support for all histograms, as well
899 // as startup/teardown of this service. 899 // as startup/teardown of this service.
900 //------------------------------------------------------------------------------ 900 //------------------------------------------------------------------------------
901 901
902 // This singleton instance should be started during the single threaded portion 902 // This singleton instance should be started during the single threaded portion
903 // of main(), and hence it is not thread safe. It initializes globals to 903 // of main(), and hence it is not thread safe. It initializes globals to
904 // provide support for all future calls. 904 // provide support for all future calls.
905 StatisticsRecorder::StatisticsRecorder() { 905 StatisticsRecorder::StatisticsRecorder() {
906 DCHECK(!histograms_); 906 DCHECK(!histograms_);
907 lock_ = new Lock; 907 if (lock_ == NULL) {
908 // This will leak on purpose. It's the only way to make sure we won't race
909 // against the static uninitialization of the module while one of our
910 // static methods relying on the lock get called at an inappropriate time
911 // during the termination phase. Since it's a static data member, we will
912 // leak one per process, which would be similar to the instance allocated
913 // during static initialization and released only on process termination.
914 lock_ = new Lock;
915 }
916 AutoLock auto_lock(*lock_);
908 histograms_ = new HistogramMap; 917 histograms_ = new HistogramMap;
909 } 918 }
910 919
911 StatisticsRecorder::~StatisticsRecorder() { 920 StatisticsRecorder::~StatisticsRecorder() {
912 DCHECK(histograms_); 921 DCHECK(histograms_ && lock_);
913 922
914 if (dump_on_exit_) { 923 if (dump_on_exit_) {
915 std::string output; 924 std::string output;
916 WriteGraph("", &output); 925 WriteGraph("", &output);
917 LOG(INFO) << output; 926 LOG(INFO) << output;
918 } 927 }
919 // Clean up. 928 // Clean up.
920 delete histograms_; 929 HistogramMap* histograms = NULL;
921 histograms_ = NULL; 930 {
922 delete lock_; 931 AutoLock auto_lock(*lock_);
923 lock_ = NULL; 932 histograms = histograms_;
933 histograms_ = NULL;
934 }
935 delete histograms;
936 // We don't delete lock_ on purpose to avoid having to properly protect
937 // against it going away after we checked for NULL in the static methods.
924 } 938 }
925 939
926 // static 940 // static
927 bool StatisticsRecorder::WasStarted() { 941 bool StatisticsRecorder::IsActive() {
942 if (lock_ == NULL)
943 return false;
944 AutoLock auto_lock(*lock_);
928 return NULL != histograms_; 945 return NULL != histograms_;
929 } 946 }
930 947
931 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a 948 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a
932 // reference, and we are called while in the Histogram constructor. In that 949 // reference, and we are called while in the Histogram constructor. In that
933 // scenario, a ref_ptr would have incremented the ref count when the histogram 950 // scenario, a ref_ptr would have incremented the ref count when the histogram
934 // was passed to us, decremented it when we returned, and the instance would be 951 // was passed to us, decremented it when we returned, and the instance would be
935 // destroyed before assignment (when value was returned by new). 952 // destroyed before assignment (when value was returned by new).
936 // static 953 // static
937 void StatisticsRecorder::Register(Histogram* histogram) { 954 void StatisticsRecorder::Register(Histogram* histogram) {
955 if (lock_ == NULL)
956 return;
957 AutoLock auto_lock(*lock_);
938 if (!histograms_) 958 if (!histograms_)
939 return; 959 return;
940 const std::string name = histogram->histogram_name(); 960 const std::string name = histogram->histogram_name();
941 AutoLock auto_lock(*lock_);
942 // Avoid overwriting a previous registration. 961 // Avoid overwriting a previous registration.
943 if (histograms_->end() == histograms_->find(name)) 962 if (histograms_->end() == histograms_->find(name))
944 (*histograms_)[name] = histogram; 963 (*histograms_)[name] = histogram;
945 } 964 }
946 965
947 // static 966 // static
948 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, 967 void StatisticsRecorder::WriteHTMLGraph(const std::string& query,
949 std::string* output) { 968 std::string* output) {
950 if (!histograms_) 969 if (!IsActive())
951 return; 970 return;
952 output->append("<html><head><title>About Histograms"); 971 output->append("<html><head><title>About Histograms");
953 if (!query.empty()) 972 if (!query.empty())
954 output->append(" - " + query); 973 output->append(" - " + query);
955 output->append("</title>" 974 output->append("</title>"
956 // We'd like the following no-cache... but it doesn't work. 975 // We'd like the following no-cache... but it doesn't work.
957 // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" 976 // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">"
958 "</head><body>"); 977 "</head><body>");
959 978
960 Histograms snapshot; 979 Histograms snapshot;
961 GetSnapshot(query, &snapshot); 980 GetSnapshot(query, &snapshot);
962 for (Histograms::iterator it = snapshot.begin(); 981 for (Histograms::iterator it = snapshot.begin();
963 it != snapshot.end(); 982 it != snapshot.end();
964 ++it) { 983 ++it) {
965 (*it)->WriteHTMLGraph(output); 984 (*it)->WriteHTMLGraph(output);
966 output->append("<br><hr><br>"); 985 output->append("<br><hr><br>");
967 } 986 }
968 output->append("</body></html>"); 987 output->append("</body></html>");
969 } 988 }
970 989
971 // static 990 // static
972 void StatisticsRecorder::WriteGraph(const std::string& query, 991 void StatisticsRecorder::WriteGraph(const std::string& query,
973 std::string* output) { 992 std::string* output) {
974 if (!histograms_) 993 if (!IsActive())
975 return; 994 return;
976 if (query.length()) 995 if (query.length())
977 StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); 996 StringAppendF(output, "Collections of histograms for %s\n", query.c_str());
978 else 997 else
979 output->append("Collections of all histograms\n"); 998 output->append("Collections of all histograms\n");
980 999
981 Histograms snapshot; 1000 Histograms snapshot;
982 GetSnapshot(query, &snapshot); 1001 GetSnapshot(query, &snapshot);
983 for (Histograms::iterator it = snapshot.begin(); 1002 for (Histograms::iterator it = snapshot.begin();
984 it != snapshot.end(); 1003 it != snapshot.end();
985 ++it) { 1004 ++it) {
986 (*it)->WriteAscii(true, "\n", output); 1005 (*it)->WriteAscii(true, "\n", output);
987 output->append("\n"); 1006 output->append("\n");
988 } 1007 }
989 } 1008 }
990 1009
991 // static 1010 // static
992 void StatisticsRecorder::GetHistograms(Histograms* output) { 1011 void StatisticsRecorder::GetHistograms(Histograms* output) {
1012 if (lock_ == NULL)
1013 return;
1014 AutoLock auto_lock(*lock_);
993 if (!histograms_) 1015 if (!histograms_)
994 return; 1016 return;
995 AutoLock auto_lock(*lock_);
996 for (HistogramMap::iterator it = histograms_->begin(); 1017 for (HistogramMap::iterator it = histograms_->begin();
997 histograms_->end() != it; 1018 histograms_->end() != it;
998 ++it) { 1019 ++it) {
999 DCHECK_EQ(it->first, it->second->histogram_name()); 1020 DCHECK_EQ(it->first, it->second->histogram_name());
1000 output->push_back(it->second); 1021 output->push_back(it->second);
1001 } 1022 }
1002 } 1023 }
1003 1024
1004 bool StatisticsRecorder::FindHistogram(const std::string& name, 1025 bool StatisticsRecorder::FindHistogram(const std::string& name,
1005 scoped_refptr<Histogram>* histogram) { 1026 scoped_refptr<Histogram>* histogram) {
1027 if (lock_ == NULL)
1028 return false;
1029 AutoLock auto_lock(*lock_);
1006 if (!histograms_) 1030 if (!histograms_)
1007 return false; 1031 return false;
1008 AutoLock auto_lock(*lock_);
1009 HistogramMap::iterator it = histograms_->find(name); 1032 HistogramMap::iterator it = histograms_->find(name);
1010 if (histograms_->end() == it) 1033 if (histograms_->end() == it)
1011 return false; 1034 return false;
1012 *histogram = it->second; 1035 *histogram = it->second;
1013 return true; 1036 return true;
1014 } 1037 }
1015 1038
1016 // private static 1039 // private static
1017 void StatisticsRecorder::GetSnapshot(const std::string& query, 1040 void StatisticsRecorder::GetSnapshot(const std::string& query,
1018 Histograms* snapshot) { 1041 Histograms* snapshot) {
1042 if (lock_ == NULL)
1043 return;
1019 AutoLock auto_lock(*lock_); 1044 AutoLock auto_lock(*lock_);
1045 if (!histograms_)
1046 return;
1020 for (HistogramMap::iterator it = histograms_->begin(); 1047 for (HistogramMap::iterator it = histograms_->begin();
1021 histograms_->end() != it; 1048 histograms_->end() != it;
1022 ++it) { 1049 ++it) {
1023 if (it->first.find(query) != std::string::npos) 1050 if (it->first.find(query) != std::string::npos)
1024 snapshot->push_back(it->second); 1051 snapshot->push_back(it->second);
1025 } 1052 }
1026 } 1053 }
1027 1054
1028 // static 1055 // static
1029 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; 1056 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL;
1030 // static 1057 // static
1031 Lock* StatisticsRecorder::lock_ = NULL; 1058 Lock* StatisticsRecorder::lock_ = NULL;
1032 // static 1059 // static
1033 bool StatisticsRecorder::dump_on_exit_ = false; 1060 bool StatisticsRecorder::dump_on_exit_ = false;
1034 1061
1035 } // namespace base 1062 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/histogram.h ('k') | chrome/renderer/renderer_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698