summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.h.cmake.in3
-rw-r--r--src/glog/logging.h.in7
-rw-r--r--src/logging.cc31
-rw-r--r--src/logging_unittest.cc4
-rw-r--r--src/logging_unittest.err2
5 files changed, 46 insertions, 1 deletions
diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in
index 6635df1..a946451 100644
--- a/src/config.h.cmake.in
+++ b/src/config.h.cmake.in
@@ -174,6 +174,9 @@
/* location of source code */
#cmakedefine TEST_SRC_DIR ${TEST_SRC_DIR}
+/* Define to necessary thread-local storage attribute. */
+#cmakedefine GLOG_THREAD_LOCAL_STORAGE ${GLOG_THREAD_LOCAL_STORAGE}
+
/* Version number of package */
#cmakedefine VERSION
diff --git a/src/glog/logging.h.in b/src/glog/logging.h.in
index d6cc865..35c65be 100644
--- a/src/glog/logging.h.in
+++ b/src/glog/logging.h.in
@@ -1113,6 +1113,12 @@ class GOOGLE_GLOG_DLL_DECL LogStreamBuf : public std::streambuf {
LogStreamBuf(char *buf, int len) {
setp(buf, buf + len - 2);
}
+
+ // Resets the buffer. Useful if we reuse it by means of TLS.
+ void reset() {
+ setp(pbase(), epptr());
+ }
+
// This effectively ignores overflow.
virtual int_type overflow(int_type ch) {
return ch;
@@ -1175,6 +1181,7 @@ public:
size_t pcount() const { return streambuf_.pcount(); }
char* pbase() const { return streambuf_.pbase(); }
char* str() const { return pbase(); }
+ void reset() { streambuf_.reset(); }
private:
LogStream(const LogStream&);
diff --git a/src/logging.cc b/src/logging.cc
index 46a0f5a..0d9aad8 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -331,6 +331,7 @@ const size_t LogMessage::kMaxLogMessageLen = 30000;
struct LogMessage::LogMessageData {
LogMessageData();
+ void reset();
int preserved_errno_; // preserved errno
// Buffer space; contains complete message text.
@@ -1145,10 +1146,22 @@ static bool fatal_msg_exclusive = true;
static LogMessage::LogMessageData fatal_msg_data_exclusive;
static LogMessage::LogMessageData fatal_msg_data_shared;
+#ifdef GLOG_THREAD_LOCAL_STORAGE
+// Static thread-local log data space to use, because typically at most one
+// LogMessageData object exists (in this case glog makes zero heap memory
+// allocations).
+static GLOG_THREAD_LOCAL_STORAGE bool thread_data_available = true;
+static GLOG_THREAD_LOCAL_STORAGE LogMessage::LogMessageData thread_msg_data;
+#endif // defined(GLOG_THREAD_LOCAL_STORAGE)
+
LogMessage::LogMessageData::LogMessageData()
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {
}
+void LogMessage::LogMessageData::reset() {
+ stream_.reset();
+}
+
LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
int ctr, void (LogMessage::*send_method)())
: allocated_(NULL) {
@@ -1201,8 +1214,22 @@ void LogMessage::Init(const char* file,
void (LogMessage::*send_method)()) {
allocated_ = NULL;
if (severity != GLOG_FATAL || !exit_on_dfatal) {
+#ifdef GLOG_THREAD_LOCAL_STORAGE
+ // No need for locking, because this is thread local.
+ if (thread_data_available) {
+ thread_data_available = false;
+ data_ = &thread_msg_data;
+ // Make sure to clear log data since it may have been used and filled with
+ // data. We do not want to append the new message to the previous one.
+ data_->reset();
+ } else {
+ allocated_ = new LogMessageData();
+ data_ = allocated_;
+ }
+#else // !defined(GLOG_THREAD_LOCAL_STORAGE)
allocated_ = new LogMessageData();
data_ = allocated_;
+#endif // defined(GLOG_THREAD_LOCAL_STORAGE)
data_->first_fatal_ = false;
} else {
MutexLock l(&fatal_msg_lock);
@@ -1271,6 +1298,10 @@ void LogMessage::Init(const char* file,
LogMessage::~LogMessage() {
Flush();
+#ifdef GLOG_THREAD_LOCAL_STORAGE
+ if (data_ == &thread_msg_data)
+ thread_data_available = true;
+#endif // defined(GLOG_THREAD_LOCAL_STORAGE)
delete allocated_;
}
diff --git a/src/logging_unittest.cc b/src/logging_unittest.cc
index 97cbeaa..600cd06 100644
--- a/src/logging_unittest.cc
+++ b/src/logging_unittest.cc
@@ -272,12 +272,14 @@ void TestLogging(bool check_counts) {
LOG(ERROR) << string("foo") << ' '<< j << ' ' << setw(10) << j << " "
<< setw(1) << hex << j;
+ LOG(ERROR) << (&LOG(ERROR) && 0) << " nested LOG";
+
LogMessage("foo", LogMessage::kNoLogPrefix, GLOG_INFO).stream() << "no prefix";
if (check_counts) {
CHECK_EQ(base_num_infos + 14, LogMessage::num_messages(GLOG_INFO));
CHECK_EQ(base_num_warning + 3, LogMessage::num_messages(GLOG_WARNING));
- CHECK_EQ(base_num_errors + 15, LogMessage::num_messages(GLOG_ERROR));
+ CHECK_EQ(base_num_errors + 17, LogMessage::num_messages(GLOG_ERROR));
}
}
diff --git a/src/logging_unittest.err b/src/logging_unittest.err
index 4f80bf5..e08836f 100644
--- a/src/logging_unittest.err
+++ b/src/logging_unittest.err
@@ -74,6 +74,8 @@ WDATE TIME__ THREADID logging_unittest.cc:LINE] log_if this
IDATE TIME__ THREADID logging_unittest.cc:LINE] array
IDATE TIME__ THREADID logging_unittest.cc:LINE] const array
EDATE TIME__ THREADID logging_unittest.cc:LINE] foo 1000 0000001000 3e8
+EDATE TIME__ THREADID logging_unittest.cc:LINE] 0 nested LOG
+EDATE TIME__ THREADID logging_unittest.cc:LINE]
no prefix
IDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: foo bar 10 3.400000
WDATE TIME__ THREADID logging_unittest.cc:LINE] RAW: array