diff --git a/CMakeLists.txt b/CMakeLists.txt index d6168fe..dca6850 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,12 @@ thread_local int tls; int main() { } " HAVE_CXX11_TLS) +check_cxx_source_compiles (" +#include +std::aligned_storage::type data; +int main() { } +" HAVE_ALIGNED_STORAGE) + if (WITH_TLS) # Cygwin does not support the thread attribute. Don't bother. if (HAVE_GCC_TLS) diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in index 2ee3291..ee8cdfe 100644 --- a/src/config.h.cmake.in +++ b/src/config.h.cmake.in @@ -189,6 +189,9 @@ /* Define to necessary thread-local storage attribute. */ #cmakedefine GLOG_THREAD_LOCAL_STORAGE ${GLOG_THREAD_LOCAL_STORAGE} +/* Check whether aligned_storage and alignof present */ +#cmakedefine HAVE_ALIGNED_STORAGE ${HAVE_ALIGNED_STORAGE} + /* Version number of package */ #cmakedefine VERSION diff --git a/src/logging.cc b/src/logging.cc index 7b33cae..8bc4066 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -1153,8 +1153,16 @@ static LogMessage::LogMessageData fatal_msg_data_shared; // 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 char thread_msg_data[sizeof(LogMessage::LogMessageData)]; -#endif // defined(GLOG_THREAD_LOCAL_STORAGE) + +#ifdef HAVE_ALIGNED_STORAGE +static GLOG_THREAD_LOCAL_STORAGE + std::aligned_storage::type thread_msg_data; +#else +static GLOG_THREAD_LOCAL_STORAGE + char thread_msg_data[sizeof(void*) + sizeof(LogMessage::LogMessageData)]; +#endif // HAVE_ALIGNED_STORAGE +#endif // defined(GLOG_THREAD_LOCAL_STORAGE) LogMessage::LogMessageData::LogMessageData() : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) { @@ -1213,10 +1221,19 @@ void LogMessage::Init(const char* file, allocated_ = NULL; if (severity != GLOG_FATAL || !exit_on_dfatal) { #ifdef GLOG_THREAD_LOCAL_STORAGE + const uintptr_t kAlign = sizeof(void*) - 1; + // No need for locking, because this is thread local. if (thread_data_available) { thread_data_available = false; +#ifdef HAVE_ALIGNED_STORAGE data_ = new (&thread_msg_data) LogMessageData; +#else + char* align_ptr = + reinterpret_cast(reinterpret_cast(thread_msg_data + kAlign) & ~kAlign); + data_ = new (align_ptr) LogMessageData; + assert(reinterpret_cast(align_ptr) % sizeof(void*) == 0); +#endif } else { allocated_ = new LogMessageData(); data_ = allocated_; @@ -1294,7 +1311,7 @@ void LogMessage::Init(const char* file, LogMessage::~LogMessage() { Flush(); #ifdef GLOG_THREAD_LOCAL_STORAGE - if (data_ == static_cast(thread_msg_data)) { + if (data_ == static_cast(&thread_msg_data)) { data_->~LogMessageData(); thread_data_available = true; }