Index: util/thread/thread_log_messages.cc |
diff --git a/util/thread/thread_log_messages.cc b/util/thread/thread_log_messages.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f3af8a8371df3b53088a7df01b7b55fdbf25ce34 |
--- /dev/null |
+++ b/util/thread/thread_log_messages.cc |
@@ -0,0 +1,98 @@ |
+// Copyright 2015 The Crashpad Authors. All rights reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include "util/thread/thread_log_messages.h" |
+ |
+#include "base/lazy_instance.h" |
+#include "base/logging.h" |
+#include "base/threading/thread_local_storage.h" |
+ |
+namespace crashpad { |
+ |
+namespace { |
+ |
+// While an object of this class exists, it will be set as the log message |
+// handler. A thread may register its thread-specific log message list to |
+// receive messages produced just on that thread. |
+// |
+// Only one object of this class may exist in the program at a time. There must |
+// not be any log message handler in effect when it is created, and nothing else |
+// can be set as a log message handler while an object of this class exists. |
+// |
+// Practically, the only object of this class that might exist is managed by the |
+// g_master lazy instance, which will create it upon first use. |
+class ThreadLogMessagesMaster { |
+ public: |
+ ThreadLogMessagesMaster() { |
+ DCHECK(!tls_.initialized()); |
+ CHECK(tls_.Initialize(nullptr)); |
+ |
+ DCHECK(!logging::GetLogMessageHandler()); |
+ logging::SetLogMessageHandler(LogMessageHandler); |
+ } |
+ |
+ ~ThreadLogMessagesMaster() { |
+ DCHECK_EQ(logging::GetLogMessageHandler(), LogMessageHandler); |
+ logging::SetLogMessageHandler(nullptr); |
+ |
+ tls_.Free(); |
+ } |
+ |
+ void SetThreadMessageList(std::vector<std::string>* message_list) { |
+ DCHECK_EQ(logging::GetLogMessageHandler(), LogMessageHandler); |
+ DCHECK_NE(tls_.Get() != nullptr, message_list != nullptr); |
+ tls_.Set(message_list); |
+ } |
+ |
+ private: |
+ static bool LogMessageHandler(logging::LogSeverity severity, |
+ const char* file_path, |
+ int line, |
+ size_t message_start, |
+ const std::string& string) { |
+ std::vector<std::string>* log_messages = |
+ reinterpret_cast<std::vector<std::string>*>(tls_.Get()); |
+ if (log_messages) { |
+ log_messages->push_back(string); |
+ } |
+ |
+ // Don’t consume the message. Allow it to be logged as if nothing was set as |
+ // the log message handler. |
+ return false; |
+ } |
+ |
+ static base::ThreadLocalStorage::StaticSlot tls_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ThreadLogMessagesMaster); |
+}; |
+ |
+// static |
+base::ThreadLocalStorage::StaticSlot ThreadLogMessagesMaster::tls_ |
+ = TLS_INITIALIZER; |
+ |
+base::LazyInstance<ThreadLogMessagesMaster>::Leaky g_master = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+} // namespace |
+ |
+ThreadLogMessages::ThreadLogMessages() |
+ : log_messages_() { |
+ g_master.Get().SetThreadMessageList(&log_messages_); |
+} |
+ |
+ThreadLogMessages::~ThreadLogMessages() { |
+ g_master.Get().SetThreadMessageList(nullptr); |
+} |
+ |
+} // namespace crashpad |