$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r86390 - in trunk: boost/sync/detail libs/sync/build libs/sync/src
From: andrey.semashev_at_[hidden]
Date: 2013-10-22 09:31:21
Author: andysem
Date: 2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)
New Revision: 86390
URL: http://svn.boost.org/trac/boost/changeset/86390
Log:
Added preliminary implementation of internal TLS.
Added:
   trunk/libs/sync/build/
   trunk/libs/sync/build/Jamfile.v2   (contents, props changed)
   trunk/libs/sync/src/
   trunk/libs/sync/src/tss_manager.hpp   (contents, props changed)
   trunk/libs/sync/src/tss_pthread.cpp   (contents, props changed)
   trunk/libs/sync/src/tss_windows.cpp   (contents, props changed)
   trunk/libs/sync/src/tss_windows_dll.cpp   (contents, props changed)
   trunk/libs/sync/src/tss_windows_hooks.hpp   (contents, props changed)
   trunk/libs/sync/src/tss_windows_pe.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/sync/detail/tss.hpp           |     7                                         
   trunk/libs/sync/build/Jamfile.v2          |   179 ++++++++++++++++++++                    
   trunk/libs/sync/src/tss_manager.hpp       |   246 ++++++++++++++++++++++++++++            
   trunk/libs/sync/src/tss_pthread.cpp       |   129 ++++++++++++++                          
   trunk/libs/sync/src/tss_windows.cpp       |   188 +++++++++++++++++++++                   
   trunk/libs/sync/src/tss_windows_dll.cpp   |    86 +++++++++                               
   trunk/libs/sync/src/tss_windows_hooks.hpp |    75 ++++++++                                
   trunk/libs/sync/src/tss_windows_pe.cpp    |   348 ++++++++++++++++++++++++++++++++++++++++
   8 files changed, 1256 insertions(+), 2 deletions(-)
Modified: trunk/boost/sync/detail/tss.hpp
==============================================================================
--- trunk/boost/sync/detail/tss.hpp	Tue Oct 22 09:28:27 2013	(r86389)
+++ trunk/boost/sync/detail/tss.hpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -30,7 +30,7 @@
 namespace detail {
 
 typedef unsigned int thread_specific_key;
-typedef void (*at_thread_exit_callback)(void*) BOOST_NOEXCEPT;
+typedef void (*at_thread_exit_callback)(void*);
 
 /*!
  * \brief Adds a callback to be invoked when the current thread terminates
@@ -47,10 +47,13 @@
  * \brief Creates a thread-specific key
  *
  * \param callback The callback to be called when a thread that used the key terminates. The callback will also be called when the key is deleted.
+ * \param cleanup_at_delete If \c true, The \a callback will be called for all non-NULL thread-specific values associated with this key at the point
+ *        of \c delete_thread_specific_key call. The user's code should be prepared that the cleanup function can be called not only in the context of the
+ *        thread that initialized the specific value.
  *
  * \returns The created key.
  */
-BOOST_SYNC_API thread_specific_key new_thread_specific_key(at_thread_exit_callback callback);
+BOOST_SYNC_API thread_specific_key new_thread_specific_key(at_thread_exit_callback callback, bool cleanup_at_delete);
 /*!
  * \brief Destroys the thread-specific key and all associated values.
  *
Added: trunk/libs/sync/build/Jamfile.v2
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/build/Jamfile.v2	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,179 @@
+# Copyright 2006-2007 Roland Schwarz.
+# Copyright 2007 Anthony Williams
+# Copyright 2011-2012 Vicente J.Botet Escriba.
+# Copyright 2013 Andrey Semashev
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+#########################################################################
+# The Boost.Sync library can be built on top of different API's on Windows.
+# Currently this is the win32 API and the pthreads API.
+# Pthread is native on unix variants.
+# To get pthread on windows you need the pthread win32 library
+# http://sourceware.org/pthreads-win32 which is available under LGPL.
+#
+# You need to provide the include path and lib path in the variables
+# PTW32_INCLUDE and PTW32_LIB respectively. You can specify these
+# paths in site-config.jam, user-config.jam or in the environment.
+# Boost.Sync also makes use of the threadapi feature defined by Boost.Thread:
+# <threadapi>win32 and <threadapi>pthread.
+#
+# To request the pthread variant on windows, from boost root you would
+# say e.g:
+# bjam msvc-8.0 --with-sync install threadapi=pthread
+#########################################################################
+
+import os ;
+import feature ;
+import indirect ;
+import path ;
+import configure ;
+
+project boost/sync
+    : source-location ../src
+    : requirements
+      <threading>multi
+      <link>static:<define>BOOST_SYNC_STATIC_LINK=1
+      <link>shared:<define>BOOST_SYNC_DYN_LINK=1
+      <define>BOOST_SYNC_BUILDING=1
+      <target-os>windows:<define>BOOST_USE_WINDOWS_H=1
+      <target-os>windows:<define>WIN32_LEAN_AND_MEAN=1
+      <library>/boost/system//boost_system
+
+    : usage-requirements  # pass these requirement to dependents (i.e. users)
+      <link>static:<define>BOOST_SYNC_STATIC_LINK=1
+      <link>shared:<define>BOOST_SYNC_DYN_LINK=1
+      <library>/boost/system//boost_system
+    ;
+
+rule win32_pthread_paths ( properties * )
+{
+    local result ;
+    local PTW32_INCLUDE ;
+    local PTW32_LIB ;
+    PTW32_INCLUDE  = [ modules.peek             : PTW32_INCLUDE ] ;
+    PTW32_LIB      = [ modules.peek             : PTW32_LIB     ] ;
+    PTW32_INCLUDE ?= [ modules.peek user-config : PTW32_INCLUDE ] ;
+    PTW32_LIB     ?= [ modules.peek user-config : PTW32_LIB     ] ;
+    PTW32_INCLUDE ?= [ modules.peek site-config : PTW32_INCLUDE ] ;
+    PTW32_LIB     ?= [ modules.peek site-config : PTW32_LIB     ] ;
+
+    if ! ( $(PTW32_INCLUDE) && $(PTW32_LIB) )
+    {
+        if  ! $(.notified)
+        {
+            echo "************************************************************" ;
+            echo "Trying to build Boost.Sync with pthread support."             ;
+            echo "If you need pthread you should specify the paths."            ;
+            echo "You can specify them in site-config.jam, user-config.jam"     ;
+            echo "or in the environment."                                       ;
+            echo "For example:"                                                 ;
+            echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include"  ;
+            echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib"          ;
+            echo "************************************************************" ;
+            .notified = true ;
+        }
+    }
+    else
+    {
+        local include_path = [ path.make $(PTW32_INCLUDE) ] ;
+        local lib_path = [ path.make $(PTW32_LIB) ] ;
+        local libname = pthread ;
+        if <toolset>msvc in $(properties)
+        {
+            libname = $(libname)VC2.lib ;
+        }
+        if <toolset>gcc in $(properties)
+        {
+            libname = lib$(libname)GC2.a ;
+        }
+        lib_path = [ path.glob $(lib_path) : $(libname) ] ;
+        if ! $(lib_path)
+        {
+            if  ! $(.notified)
+            {
+                echo "************************************************************" ;
+                echo "Trying to build Boost.Sync with pthread support."             ;
+                echo "But the library" $(libname) "could not be found in path"      ;
+                echo $(PTW32_LIB)                                                   ;
+                echo "************************************************************" ;
+                .notified = true ;
+            }
+        }
+        else
+        {
+            result += <include>$(include_path) ;
+            result += <library>$(lib_path) ;
+        }
+    }
+    return $(result) ;
+}
+
+rule usage-requirements ( properties * )
+{
+    local result ;
+    if <threadapi>pthread in $(properties)
+    {
+        if <target-os>windows in $(properties)
+        {
+            result += <define>BOOST_SYNC_USE_PTHREAD ;
+            result += [ win32_pthread_paths $(properties) ] ;
+            # TODO: What is for static linking? Is the <library> also needed
+            # in that case?
+        }
+    }
+
+    return $(result) ;
+}
+
+rule requirements ( properties * )
+{
+    local result ;
+
+    if <threadapi>pthread in $(properties)
+    {
+        result += <define>BOOST_SYNC_USE_PTHREAD ;
+        if <target-os>windows in $(properties)
+        {
+            local paths = [ win32_pthread_paths $(properties) ] ;
+            if $(paths)
+            {
+                result += $(paths) ;
+            }
+            else
+            {
+                result = <build>no ;
+            }
+        }
+    }
+
+    return $(result) ;
+}
+
+alias sync_platform_sources
+    :
+      tss_windows_dll.cpp
+      tss_windows_pe.cpp
+      tss_windows.cpp
+      tss_pthread.cpp
+    :
+      <target-os>windows
+    ;
+
+alias sync_platform_sources
+    :
+      tss_pthread.cpp
+    ;
+
+explicit sync_platform_sources ;
+
+lib boost_sync
+    :
+      sync_platform_sources
+    :
+      <conditional>@requirements
+    :
+    :
+      <conditional>@usage-requirements
+    ;
Added: trunk/libs/sync/src/tss_manager.hpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/src/tss_manager.hpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,246 @@
+/*
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * (C) Copyright 2013 Andrey Semashev
+ */
+/*!
+ * \file   tss_manager.hpp
+ *
+ * \brief  This header is the Boost.Sync library implementation, see the library documentation
+ *         at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+#ifndef BOOST_SYNC_IMPL_TSS_MANAGER_HPP_INCLUDED_
+#define BOOST_SYNC_IMPL_TSS_MANAGER_HPP_INCLUDED_
+
+#include <stack>
+#include <vector>
+#include <boost/assert.hpp>
+#include <boost/intrusive/options.hpp>
+#include <boost/intrusive/list.hpp>
+#include <boost/intrusive/list_hook.hpp>
+#include <boost/sync/detail/config.hpp>
+#include <boost/sync/locks/lock_guard.hpp>
+#include <boost/sync/locks/unique_lock.hpp>
+#include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/detail/tss.hpp>
+#include <boost/sync/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+class tss_manager
+{
+public:
+    typedef intrusive::list_base_hook<
+        intrusive::tag< struct for_thread_context_list >,
+        intrusive::link_mode< intrusive::safe_link >
+    > thread_context_list_hook;
+
+    class thread_context :
+        public thread_context_list_hook
+    {
+        friend class tss_manager;
+
+    private:
+        struct at_exit_entry
+        {
+            at_thread_exit_callback callback;
+            void* context;
+        };
+
+    private:
+        std::vector< void* > m_storage;
+        std::vector< at_exit_entry > m_at_exit_functions;
+
+    public:
+        void* get_value(thread_specific_key key) const BOOST_NOEXCEPT
+        {
+            if (key < m_storage.size())
+                return m_storage[key];
+            else
+                return NULL;
+        }
+
+        void set_value(thread_specific_key key, void* value)
+        {
+            if (key >= m_storage.size())
+                m_storage.resize(key + 1, static_cast< void* >(NULL));
+            m_storage[key] = value;
+        }
+
+        void add_at_exit_entry(at_thread_exit_callback callback, void* context)
+        {
+            at_exit_entry entry;
+            entry.callback = callback;
+            entry.context = context;
+            m_at_exit_functions.push_back(entry);
+        }
+    };
+
+private:
+    typedef sync::mutex mutex_type;
+
+    typedef intrusive::list<
+        thread_context,
+        intrusive::base_hook< thread_context_list_hook >,
+        intrusive::constant_time_size< false >
+    > thread_context_list;
+
+    struct cleanup_info
+    {
+        at_thread_exit_callback cleanup;
+        bool cleanup_at_delete;
+    };
+
+private:
+    //! Thread synchronization primitive
+    mutex_type m_mutex;
+    //! The list of thread contexts
+    thread_context_list m_thread_contexts;
+    //! The list of cleanup functions for TLS
+    std::vector< cleanup_info > m_storage_cleanup;
+    //! The list of TLS keys released
+    std::stack< thread_specific_key > m_freed_keys;
+
+public:
+    BOOST_DEFAULTED_FUNCTION(tss_manager(), {})
+
+    ~tss_manager()
+    {
+        while (!m_thread_contexts.empty())
+            destroy_thread_context(&m_thread_contexts.front());
+    }
+
+    thread_context* create_thread_context()
+    {
+        thread_context* p = new thread_context();
+
+        sync::lock_guard< mutex_type > lock(m_mutex);
+        m_thread_contexts.push_back(*p);
+
+        return p;
+    }
+
+    void destroy_thread_context(thread_context* p) BOOST_NOEXCEPT
+    {
+        // Run cleanup functions
+        while (!p->m_at_exit_functions.empty())
+        {
+            std::vector< thread_context::at_exit_entry > at_exit_functions;
+            at_exit_functions.swap(p->m_at_exit_functions);
+
+            for (std::vector< thread_context::at_exit_entry >::reverse_iterator it = at_exit_functions.rbegin(), end = at_exit_functions.rend(); it != end; ++it)
+            {
+                it->callback(it->context);
+            }
+        }
+
+        // Destroy TLS
+        while (!p->m_storage.empty())
+        {
+            std::vector< void* > storage;
+            storage.swap(p->m_storage);
+            for (thread_specific_key key = 0, n = storage.size(); key < n; ++key)
+            {
+                void* const value = storage[key];
+                if (value)
+                {
+                    const at_thread_exit_callback cleanup = m_storage_cleanup[key].cleanup;
+                    if (cleanup)
+                        cleanup(value);
+                }
+            }
+        }
+
+        // Destroy the context
+        {
+            sync::lock_guard< mutex_type > lock(m_mutex);
+            m_thread_contexts.erase(m_thread_contexts.iterator_to(*p));
+        }
+        delete p;
+    }
+
+    thread_specific_key new_key(at_thread_exit_callback cleanup, bool cleanup_at_delete)
+    {
+        sync::lock_guard< mutex_type > lock(m_mutex);
+
+        // See if we can recycle some key
+        thread_specific_key key;
+        if (!m_freed_keys.empty())
+        {
+            key = m_freed_keys.top();
+            m_freed_keys.pop();
+            cleanup_info& info = m_storage_cleanup[key];
+            info.cleanup = cleanup;
+            info.cleanup_at_delete = cleanup_at_delete;
+        }
+        else
+        {
+            key = static_cast< thread_specific_key >(m_storage_cleanup.size());
+            cleanup_info info;
+            info.cleanup = cleanup;
+            info.cleanup_at_delete = cleanup_at_delete;
+            m_storage_cleanup.push_back(info);
+        }
+
+        return key;
+    }
+
+    void delete_key(thread_specific_key key)
+    {
+        sync::unique_lock< mutex_type > lock(m_mutex);
+
+        BOOST_ASSERT(key < m_storage_cleanup.size());
+
+        cleanup_info& info = m_storage_cleanup[key];
+        if (info.cleanup_at_delete)
+        {
+            std::vector< void* > storage;
+            const at_thread_exit_callback cleanup = info.cleanup;
+            info.cleanup = NULL;
+
+            for (thread_context_list::iterator it = m_thread_contexts.begin(), end = m_thread_contexts.end(); it != end; ++it)
+            {
+                if (it->m_storage.size() > key && it->m_storage[key] != NULL)
+                {
+                    if (cleanup)
+                        storage.push_back(it->m_storage[key]);
+                    it->m_storage[key] = NULL;
+                }
+            }
+
+            m_freed_keys.push(key);
+
+            lock.unlock();
+
+            // Run cleanup routines while the lock is released
+            for (std::vector< void* >::iterator it = storage.begin(), end = storage.end(); it != end; ++it)
+            {
+                cleanup(*it);
+            }
+        }
+    }
+
+    BOOST_DELETED_FUNCTION(tss_manager(tss_manager const&))
+    BOOST_DELETED_FUNCTION(tss_manager& operator= (tss_manager const&))
+};
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_IMPL_TSS_MANAGER_HPP_INCLUDED_
Added: trunk/libs/sync/src/tss_pthread.cpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/src/tss_pthread.cpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,129 @@
+/*
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * (C) Copyright 2004 Michael Glassford
+ * (C) Copyright 2013 Andrey Semashev
+ */
+/*!
+ * \file   tss_pthread.cpp
+ *
+ * \brief  This header is the Boost.Sync library implementation, see the library documentation
+ *         at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+#include <boost/sync/detail/config.hpp>
+
+#if !defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+
+#include <cstddef>
+#include <cstdlib>
+#include <pthread.h>
+#include <boost/sync/detail/tss.hpp>
+#include "tss_manager.hpp"
+#include <boost/sync/detail/header.hpp>
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+namespace {
+
+static pthread_once_t init_tss_once_flag = PTHREAD_ONCE_INIT;
+static tss_manager* tss_mgr = NULL;
+static pthread_key_t tss_key;
+
+extern "C" {
+
+static void tss_cleanup(void* p)
+{
+    if (tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(p))
+    {
+        tss_mgr->destroy_thread_context(ctx);
+    }
+}
+
+static void init_tss()
+{
+    try
+    {
+        tss_mgr = new tss_manager();
+    }
+    catch (...)
+    {
+        std::abort();
+    }
+
+    if (pthread_key_create(&tss_key, &tss_cleanup) != 0)
+        std::abort();
+}
+
+} // extern "C"
+
+} // namespace
+
+BOOST_SYNC_API void add_thread_exit_callback(at_thread_exit_callback callback, void* context)
+{
+    pthread_once(&init_tss_once_flag, &init_tss);
+    tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+
+    if (!ctx)
+    {
+        ctx = tss_mgr->create_thread_context();
+        pthread_setspecific(tss_key, ctx);
+    }
+
+    ctx->add_at_exit_entry(callback, context);
+}
+
+BOOST_SYNC_API thread_specific_key new_thread_specific_key(at_thread_exit_callback callback, bool cleanup_at_delete)
+{
+    pthread_once(&init_tss_once_flag, &init_tss);
+    return tss_mgr->new_key(callback, cleanup_at_delete);
+}
+
+BOOST_SYNC_API void delete_thread_specific_key(thread_specific_key key) BOOST_NOEXCEPT
+{
+    try
+    {
+        tss_mgr->delete_key(key);
+    }
+    catch (...)
+    {
+        std::abort();
+    }
+}
+
+BOOST_SYNC_API void* get_thread_specific(thread_specific_key key)
+{
+    tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+    if (ctx)
+        return ctx->get_value(key);
+    return NULL;
+}
+
+BOOST_SYNC_API void set_thread_specific(thread_specific_key key, void* p)
+{
+    tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+
+    if (!ctx)
+    {
+        ctx = tss_mgr->create_thread_context();
+        pthread_setspecific(tss_key, ctx);
+    }
+
+    ctx->set_value(key, p);
+}
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // !defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
Added: trunk/libs/sync/src/tss_windows.cpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/src/tss_windows.cpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,188 @@
+/*
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * (C) Copyright 2004 Michael Glassford
+ * (C) Copyright 2013 Andrey Semashev
+ */
+/*!
+ * \file   tss_windows.cpp
+ *
+ * \brief  This header is the Boost.Sync library implementation, see the library documentation
+ *         at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+#include <boost/sync/detail/config.hpp>
+
+#if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+
+#include <cstddef>
+#include <cstdlib>
+#include <boost/sync/detail/interlocked.hpp>
+#include <boost/sync/detail/tss.hpp>
+#include "tss_manager.hpp"
+#include "tss_windows_hooks.hpp"
+#include <windows.h>
+#include <boost/sync/detail/header.hpp>
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+namespace {
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+static INIT_ONCE init_tss_once_flag = INIT_ONCE_STATIC_INIT;
+#else
+static long init_tss_once_flag = 0;
+#endif
+static tss_manager* tss_mgr = NULL;
+static DWORD tss_key = TLS_OUT_OF_INDEXES;
+
+extern "C" {
+
+static BOOL WINAPI init_tss(void*, void*, void**)
+{
+    try
+    {
+        tss_mgr = new tss_manager();
+    }
+    catch (...)
+    {
+        std::abort();
+    }
+
+    tss_key = TlsAlloc();
+    if (tss_key == TLS_OUT_OF_INDEXES)
+        std::abort();
+
+    return TRUE;
+}
+
+} // extern "C"
+
+#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+BOOST_FORCEINLINE void init_tss_once()
+{
+    InitOnceExecuteOnce(&init_tss_once_flag, (PINIT_ONCE_FN)&init_tss, NULL, NULL);
+}
+
+#else // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+BOOST_FORCEINLINE void init_tss_once()
+{
+    if (const_cast< long volatile& >(init_tss_once_flag) != 2)
+    {
+        while (true)
+        {
+            long old_val = BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&init_tss_once_flag, 1, 0);
+            if (old_val == 2)
+                break;
+            else if (old_val == 1)
+                SwitchToThread();
+            else
+            {
+                init_tss(NUll, NULL, NULL);
+                BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&init_tss_once_flag, 2);
+                break;
+            }
+        }
+    }
+}
+
+#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
+
+} // namespace
+
+namespace windows {
+
+void on_process_enter()
+{
+}
+
+void on_process_exit()
+{
+}
+
+void on_thread_enter()
+{
+}
+
+void on_thread_exit()
+{
+    // This callback may be called before tss manager is initialized
+    init_tss_once();
+    if (tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(TlsGetValue(tss_key)))
+    {
+        tss_mgr->destroy_thread_context(ctx);
+    }
+}
+
+} // namespace windows
+
+BOOST_SYNC_API void add_thread_exit_callback(at_thread_exit_callback callback, void* context)
+{
+    init_tss_once();
+    tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+
+    if (!ctx)
+    {
+        ctx = tss_mgr->create_thread_context();
+        pthread_setspecific(tss_key, ctx);
+    }
+
+    ctx->add_at_exit_entry(callback, context);
+}
+
+BOOST_SYNC_API thread_specific_key new_thread_specific_key(at_thread_exit_callback callback, bool cleanup_at_delete)
+{
+    init_tss_once();
+    return tss_mgr->new_key(callback, cleanup_at_delete);
+}
+
+BOOST_SYNC_API void delete_thread_specific_key(thread_specific_key key) BOOST_NOEXCEPT
+{
+    try
+    {
+        tss_mgr->delete_key(key);
+    }
+    catch (...)
+    {
+        std::abort();
+    }
+}
+
+BOOST_SYNC_API void* get_thread_specific(thread_specific_key key)
+{
+    tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(TlsGetValue(tss_key));
+    if (ctx)
+        return ctx->get_value(key);
+    return NULL;
+}
+
+BOOST_SYNC_API void set_thread_specific(thread_specific_key key, void* p)
+{
+    tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(TlsGetValue(tss_key));
+
+    if (!ctx)
+    {
+        ctx = tss_mgr->create_thread_context();
+        TlsSetValue(tss_key, ctx);
+    }
+
+    ctx->set_value(key, p);
+}
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
Added: trunk/libs/sync/src/tss_windows_dll.cpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/src/tss_windows_dll.cpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,86 @@
+// (C) Copyright Michael Glassford 2004.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/sync/detail/config.hpp>
+
+#if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) && defined(BOOST_SYNC_DYN_LINK)
+
+#include <windows.h>
+#include "tss_windows_hooks.hpp"
+
+#if defined(__BORLANDC__)
+extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
+#elif defined(_WIN32_WCE)
+extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
+#else
+extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
+#endif
+{
+    switch(dwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        {
+            boost::on_process_enter();
+            boost::on_thread_enter();
+            break;
+        }
+
+    case DLL_THREAD_ATTACH:
+        {
+            boost::on_thread_enter();
+            break;
+        }
+
+    case DLL_THREAD_DETACH:
+        {
+            boost::on_thread_exit();
+            break;
+        }
+
+    case DLL_PROCESS_DETACH:
+        {
+            boost::on_thread_exit();
+            boost::on_process_exit();
+            break;
+        }
+    }
+
+    return TRUE;
+}
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+namespace windows {
+
+void tss_cleanup_implemented()
+{
+    /*
+    This function's sole purpose is to cause a link error in cases where
+    automatic tss cleanup is not implemented by Boost.Threads as a
+    reminder that user code is responsible for calling the necessary
+    functions at the appropriate times (and for implementing an a
+    tss_cleanup_implemented() function to eliminate the linker's
+    missing symbol error).
+
+    If Boost.Threads later implements automatic tss cleanup in cases
+    where it currently doesn't (which is the plan), the duplicate
+    symbol error will warn the user that their custom solution is no
+    longer needed and can be removed.
+    */
+}
+
+} // namespace windows
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+#endif // defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) && defined(BOOST_SYNC_DYN_LINK)
Added: trunk/libs/sync/src/tss_windows_hooks.hpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/src/tss_windows_hooks.hpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,75 @@
+/*
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * (C) Copyright 2004 Michael Glassford
+ * (C) Copyright 2013 Andrey Semashev
+ */
+/*!
+ * \file   tss_windows_hooks.hpp
+ *
+ * \brief  This header is the Boost.Sync library implementation, see the library documentation
+ *         at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+#ifndef BOOST_SYNC_IMPL_TSS_WINDOWS_HOOKS_HPP_INCLUDED_
+#define BOOST_SYNC_IMPL_TSS_WINDOWS_HOOKS_HPP_INCLUDED_
+
+#include <boost/sync/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+namespace windows {
+
+/*!
+ * Function to be called when the exe or dll that uses Boost.Sync first starts or is first loaded.
+ * Should be called only before the first call to \c on_thread_enter. Called automatically by
+ * Boost.Sync when a method for doing so has been discovered. May be omitted; may be called multiple times.
+ */
+void on_process_enter();
+
+/*!
+ * Function to be called when the exe or dll that uses Boost.Sync first starts or is first loaded.
+ * Should be called only after the last call to \c on_thread_exit. Called automatically by Boost.Sync
+ * when a method for doing so has been discovered. Must not be omitted; may be called multiple times.
+ */
+void on_process_exit();
+
+/*!
+ * Function to be called just after a thread starts in an exe or dll that uses Boost.Sync.
+ * Must be called in the context of the thread that is starting. Called automatically by Boost.Sync
+ * when a method for doing so has been discovered. May be omitted; may be called multiple times.
+ */
+void on_thread_enter();
+
+/*!
+ * Function to be called just be fore a thread ends in an exe or dll that uses Boost.Sync.
+ * Must be called in the context of the thread that is ending. Called automatically by Boost.Sync
+ * when a method for doing so has been discovered. Must not be omitted; may be called multiple times.
+ */
+void on_thread_exit();
+
+/*!
+ * Dummy function used both to detect whether tss cleanup cleanup has been implemented and to force
+ * it to be linked into the Boost.Sync library.
+ */
+void tss_cleanup_implemented();
+
+} // namespace windows
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+#endif // BOOST_SYNC_IMPL_TSS_WINDOWS_HOOKS_HPP_INCLUDED_
Added: trunk/libs/sync/src/tss_windows_pe.cpp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ trunk/libs/sync/src/tss_windows_pe.cpp	2013-10-22 09:31:21 EDT (Tue, 22 Oct 2013)	(r86390)
@@ -0,0 +1,348 @@
+// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004.
+// (C) Copyright 2007 Roland Schwarz
+// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007 David Deakins
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/sync/detail/config.hpp>
+
+#if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) && defined(BOOST_SYNC_STATIC_LINK)
+
+#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
+
+#include <cstdlib>
+#include <windows.h>
+#include "tss_windows_hooks.hpp"
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+namespace windows {
+
+void tss_cleanup_implemented()
+{
+}
+
+} // namespace windows
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+namespace {
+
+void NTAPI on_tls_callback(void*, DWORD dwReason, PVOID)
+{
+    switch (dwReason)
+    {
+    case DLL_THREAD_DETACH:
+        {
+            boost::on_thread_exit();
+            break;
+        }
+    }
+}
+
+} // namespace
+
+#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32_MAJOR_VERSION > 3) || \
+    ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION >= 18))
+extern "C"
+{
+    PIMAGE_TLS_CALLBACK __crt_xl_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
+}
+#else
+extern "C" {
+
+    void (* after_ctors )() __attribute__((section(".ctors")))     = boost::on_process_enter;
+    void (* before_dtors)() __attribute__((section(".dtors")))     = boost::on_thread_exit;
+    void (* after_dtors )() __attribute__((section(".dtors.zzz"))) = boost::on_process_exit;
+
+    ULONG __tls_index__ = 0;
+    char __tls_end__ __attribute__((section(".tls$zzz"))) = 0;
+    char __tls_start__ __attribute__((section(".tls"))) = 0;
+
+
+    PIMAGE_TLS_CALLBACK __crt_xl_start__ __attribute__ ((section(".CRT$XLA"))) = 0;
+    PIMAGE_TLS_CALLBACK __crt_xl_end__ __attribute__ ((section(".CRT$XLZ"))) = 0;
+}
+extern "C" const IMAGE_TLS_DIRECTORY32 _tls_used __attribute__ ((section(".rdata$T"))) =
+{
+        (DWORD) &__tls_start__,
+        (DWORD) &__tls_end__,
+        (DWORD) &__tls_index__,
+        (DWORD) (&__crt_xl_start__+1),
+        (DWORD) 0,
+        (DWORD) 0
+};
+#endif
+
+
+#elif  defined(_MSC_VER) && !defined(UNDER_CE)
+
+#include <stdlib.h>
+#include <windows.h>
+#include "tss_windows_hooks.hpp"
+
+// _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp
+// into your dll; it ensures that MFC-Dll-initialization will be done properly
+// The following code is adapted from the MFC-Dll-init code
+/*
+ * _pRawDllMainOrig MUST be an extern const variable, which will be aliased to
+ * _pDefaultRawDllMainOrig if no real user definition is present, thanks to the
+ * alternatename directive.
+ */
+
+// work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008)
+#if (_MSC_VER >= 1500)
+
+extern "C" {
+extern BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID);
+extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NULL;
+#if defined (_M_IX86)
+#pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig")
+#elif defined (_M_X64) || defined (_M_ARM)
+#pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig")
+#else  /* defined (_M_X64) || defined (_M_ARM) */
+#error Unsupported platform
+#endif  /* defined (_M_X64) || defined (_M_ARM) */
+}
+
+#endif
+
+
+//Definitions required by implementation
+
+#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
+    typedef void (__cdecl *_PVFV)();
+    #define INIRETSUCCESS
+    #define PVAPI void __cdecl
+#else
+    typedef int (__cdecl *_PVFV)();
+    #define INIRETSUCCESS 0
+    #define PVAPI int __cdecl
+#endif
+
+typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
+
+//Symbols for connection to the runtime environment
+
+extern "C"
+{
+    extern DWORD _tls_used; //the tls directory (located in .rdata segment)
+    extern _TLSCB __xl_a[], __xl_z[];    //tls initializers */
+}
+
+namespace
+{
+    //Forward declarations
+
+    static PVAPI on_tls_prepare();
+    static PVAPI on_process_init();
+    static PVAPI on_process_term();
+    static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
+
+    //The .CRT$Xxx information is taken from Codeguru:
+    //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
+
+#if (_MSC_VER >= 1400)
+#pragma section(".CRT$XIU",long,read)
+#pragma section(".CRT$XCU",long,read)
+#pragma section(".CRT$XTU",long,read)
+#pragma section(".CRT$XLC",long,read)
+    __declspec(allocate(".CRT$XLC")) _TLSCB __xl_ca=on_tls_callback;
+    __declspec(allocate(".CRT$XIU"))_PVFV p_tls_prepare = on_tls_prepare;
+    __declspec(allocate(".CRT$XCU"))_PVFV p_process_init = on_process_init;
+    __declspec(allocate(".CRT$XTU"))_PVFV p_process_term = on_process_term;
+#else
+    #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
+    #   pragma data_seg(push, old_seg)
+    #endif
+        //Callback to run tls glue code first.
+        //I don't think it is necessary to run it
+        //at .CRT$XIB level, since we are only
+        //interested in thread detachement. But
+        //this could be changed easily if required.
+
+        #pragma data_seg(".CRT$XIU")
+        static _PVFV p_tls_prepare = on_tls_prepare;
+        #pragma data_seg()
+
+        //Callback after all global ctors.
+
+        #pragma data_seg(".CRT$XCU")
+        static _PVFV p_process_init = on_process_init;
+        #pragma data_seg()
+
+        //Callback for tls notifications.
+
+        #pragma data_seg(".CRT$XLB")
+        _TLSCB p_thread_callback = on_tls_callback;
+        #pragma data_seg()
+        //Callback for termination.
+
+        #pragma data_seg(".CRT$XTU")
+        static _PVFV p_process_term = on_process_term;
+        #pragma data_seg()
+    #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
+    #   pragma data_seg(pop, old_seg)
+    #endif
+#endif
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4189)
+#endif
+
+PVAPI on_tls_prepare()
+{
+    //The following line has an important side effect:
+    //if the TLS directory is not already there, it will
+    //be created by the linker. In other words, it forces a tls
+    //directory to be generated by the linker even when static tls
+    //(i.e. __declspec(thread)) is not used.
+    //The volatile should prevent the optimizer
+    //from removing the reference.
+
+    DWORD volatile dw = _tls_used;
+
+    #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
+        _TLSCB* pfbegin = __xl_a;
+        _TLSCB* pfend = __xl_z;
+        _TLSCB* pfdst = pfbegin;
+        //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks;
+
+        //The following loop will merge the address pointers
+        //into a contiguous area, since the tlssup code seems
+        //to require this (at least on MSVC 6)
+
+        while (pfbegin < pfend)
+        {
+            if (*pfbegin != 0)
+            {
+                *pfdst = *pfbegin;
+                ++pfdst;
+            }
+            ++pfbegin;
+        }
+
+        *pfdst = 0;
+    #endif
+
+    return INIRETSUCCESS;
+}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+PVAPI on_process_init()
+{
+    //Schedule on_thread_exit() to be called for the main
+    //thread before destructors of global objects have been
+    //called.
+
+    //It will not be run when 'quick' exiting the
+    //library; however, this is the standard behaviour
+    //for destructors of global objects, so that
+    //shouldn't be a problem.
+
+    atexit(boost::on_thread_exit);
+
+    //Call Boost process entry callback here
+
+    boost::on_process_enter();
+
+    return INIRETSUCCESS;
+}
+
+PVAPI on_process_term()
+{
+    boost::on_process_exit();
+    return INIRETSUCCESS;
+}
+
+void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/)
+{
+    switch (dwReason)
+    {
+    case DLL_THREAD_DETACH:
+        boost::on_thread_exit();
+        break;
+    }
+}
+
+#if (_MSC_VER >= 1500)
+BOOL WINAPI dll_callback(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
+#else
+BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID)
+#endif
+{
+    switch (dwReason)
+    {
+    case DLL_THREAD_DETACH:
+        boost::on_thread_exit();
+        break;
+    case DLL_PROCESS_DETACH:
+        boost::on_process_exit();
+        break;
+    }
+
+#if (_MSC_VER >= 1500)
+    if( _pRawDllMainOrig )
+    {
+        return _pRawDllMainOrig(hInstance, dwReason, lpReserved);
+    }
+#endif
+    return true;
+}
+
+} //namespace
+
+extern "C"
+{
+    extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID) = &dll_callback;
+}
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+namespace windows {
+
+void tss_cleanup_implemented()
+{
+    /*
+    This function's sole purpose is to cause a link error in cases where
+    automatic tss cleanup is not implemented by Boost.Threads as a
+    reminder that user code is responsible for calling the necessary
+    functions at the appropriate times (and for implementing an a
+    tss_cleanup_implemented() function to eliminate the linker's
+    missing symbol error).
+
+    If Boost.Threads later implements automatic tss cleanup in cases
+    where it currently doesn't (which is the plan), the duplicate
+    symbol error will warn the user that their custom solution is no
+    longer needed and can be removed.
+    */
+}
+
+} // namespace windows
+
+} // namespace detail
+
+} // namespace sync
+
+} // namespace boost
+
+#endif //defined(_MSC_VER) && !defined(UNDER_CE)
+
+#endif //defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI) && defined(BOOST_SYNC_STATIC_LINK)