[glibmm] Build: Use Threads::Private hen thread_local keyword is not supported.



commit 63c9c986ceb1e66c418f5863d74f078f0ec567ed
Author: Tom Schoonjans <Tom Schoonjans diamond ac uk>
Date:   Mon Mar 28 16:05:01 2016 +0100

    Build: Use Threads::Private hen thread_local keyword is not supported.
    
    This fix is necessary for compilation of glibmm on OS X, as the clang
    compiler that currently ships with XCode currently does not support this
    keyword. Bug #759791

 configure.ac                    |    6 ++++++
 glib/glibmm/dispatcher.cc       |   29 +++++++++++++++++++++++++++++
 glib/glibmm/exceptionhandler.cc |   19 +++++++++++++++++++
 3 files changed, 54 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 52a001e..70f61ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -106,6 +106,12 @@ GLIBMM_CXX_CAN_USE_NAMESPACES_INSIDE_EXTERNC
 GLIBMM_CXX_ALLOWS_STATIC_INLINE_NPOS
 GLIBMM_C_STD_TIME_T_IS_NOT_INT32
 
+# check for thread_local support
+AC_MSG_CHECKING([whether the thread_local keyword is supported])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([thread_local int i=0;], [])],
+       AC_DEFINE([GLIBMM_THREAD_LOCAL_ENABLED], [1], [thread_local keyword is available])
+       AC_MSG_RESULT([yes]) , AC_MSG_RESULT([no]))
+
 MM_ARG_ENABLE_DOCUMENTATION
 MM_ARG_WITH_TAGFILE_DOC([libstdc++.tag], [mm-common-libstdc++])
 MM_ARG_WITH_TAGFILE_DOC([libsigc++-2.0.tag], [sigc++-2.0])
diff --git a/glib/glibmm/dispatcher.cc b/glib/glibmm/dispatcher.cc
index 8525fbe..9ee3b0c 100644
--- a/glib/glibmm/dispatcher.cc
+++ b/glib/glibmm/dispatcher.cc
@@ -15,6 +15,10 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifndef GLIBMM_THREAD_LOCAL_ENABLED
+#include <glibmm/threads.h>
+#endif
+
 #include <glibmm/dispatcher.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/fileutils.h>
@@ -143,7 +147,11 @@ protected:
   explicit DispatchNotifier(const Glib::RefPtr<MainContext>& context);
 
 private:
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
   static thread_local DispatchNotifier* thread_specific_instance_;
+#else
+  static Glib::Threads::Private<DispatchNotifier> thread_specific_instance_;
+#endif
 
   std::set<const Dispatcher*> deleted_dispatchers_;
 
@@ -166,7 +174,12 @@ private:
 /**** Glib::DispatchNotifier ***********************************************/
 
 // static
+
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
 thread_local DispatchNotifier* DispatchNotifier::thread_specific_instance_ = nullptr;
+#else
+Glib::Threads::Private<DispatchNotifier> DispatchNotifier::thread_specific_instance_;
+#endif
 
 DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context)
 : deleted_dispatchers_(),
@@ -269,12 +282,20 @@ DispatchNotifier*
 DispatchNotifier::reference_instance(
   const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher)
 {
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
   DispatchNotifier* instance = thread_specific_instance_;
+#else
+  DispatchNotifier* instance = thread_specific_instance_.get();
+#endif
 
   if (!instance)
   {
     instance = new DispatchNotifier(context);
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
     thread_specific_instance_ = instance;
+#else
+    thread_specific_instance_.replace(instance);
+#endif
   }
   else
   {
@@ -302,7 +323,11 @@ DispatchNotifier::reference_instance(
 void
 DispatchNotifier::unreference_instance(DispatchNotifier* notifier, const Dispatcher* dispatcher)
 {
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
   DispatchNotifier* const instance = thread_specific_instance_;
+#else
+  DispatchNotifier* const instance = thread_specific_instance_.get();
+#endif
 
   // Yes, the notifier argument is only used to check for sanity.
   g_return_if_fail(instance == notifier);
@@ -319,8 +344,12 @@ DispatchNotifier::unreference_instance(DispatchNotifier* notifier, const Dispatc
   {
     g_return_if_fail(instance->ref_count_ == 0); // could be < 0 if messed up
 
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
     delete thread_specific_instance_;
     thread_specific_instance_ = nullptr;
+#else
+    thread_specific_instance_.replace(nullptr);
+#endif
   }
 }
 
diff --git a/glib/glibmm/exceptionhandler.cc b/glib/glibmm/exceptionhandler.cc
index c12e199..7311bbe 100644
--- a/glib/glibmm/exceptionhandler.cc
+++ b/glib/glibmm/exceptionhandler.cc
@@ -19,6 +19,9 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifndef GLIBMM_THREAD_LOCAL_ENABLED
+#include <glibmm/threads.h>
+#endif
 #include <glibmmconfig.h>
 #include <glibmm/error.h>
 #include <glibmm/exceptionhandler.h>
@@ -33,7 +36,11 @@ typedef sigc::signal<void> HandlerList;
 
 // Each thread has its own list of exception handlers
 // to avoid thread synchronization problems.
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
 static thread_local HandlerList* thread_specific_handler_list = nullptr;
+#else
+static Glib::Threads::Private<HandlerList> thread_specific_handler_list;
+#endif
 
 static void
 glibmm_exception_warning(const GError* error)
@@ -85,12 +92,20 @@ namespace Glib
 sigc::connection
 add_exception_handler(const sigc::slot<void>& slot)
 {
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
   HandlerList* handler_list = thread_specific_handler_list;
+#else
+  HandlerList* handler_list = thread_specific_handler_list.get();
+#endif
 
   if (!handler_list)
   {
     handler_list = new HandlerList();
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
     thread_specific_handler_list = handler_list;
+#else
+    thread_specific_handler_list.set(handler_list);
+#endif
   }
 
   handler_list->slots().push_front(slot);
@@ -114,7 +129,11 @@ exception_handlers_invoke() noexcept
   // handled.  If there are no more handlers in the list and the exception
   // is still unhandled, call glibmm_unexpected_exception().
 
+#ifdef GLIBMM_THREAD_LOCAL_ENABLED
   if (HandlerList* const handler_list = thread_specific_handler_list)
+#else
+  if(HandlerList *const handler_list = thread_specific_handler_list.get())
+#endif
   {
     HandlerList::iterator pslot = handler_list->slots().begin();
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]