$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r62105 - in sandbox/chrono/libs/thread/src: . pthread win32
From: vicente.botet_at_[hidden]
Date: 2010-05-20 03:48:05
Author: viboes
Date: 2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
New Revision: 62105
URL: http://svn.boost.org/trac/boost/changeset/62105
Log:
Boost.Chrono: Add Boost.Threads 1.43: port to Boost.Chrono to conform with C++0x
Added:
   sandbox/chrono/libs/thread/src/
   sandbox/chrono/libs/thread/src/pthread/
   sandbox/chrono/libs/thread/src/pthread/once.cpp   (contents, props changed)
   sandbox/chrono/libs/thread/src/pthread/thread.cpp   (contents, props changed)
   sandbox/chrono/libs/thread/src/pthread/timeconv.inl   (contents, props changed)
   sandbox/chrono/libs/thread/src/tss_null.cpp   (contents, props changed)
   sandbox/chrono/libs/thread/src/win32/
   sandbox/chrono/libs/thread/src/win32/thread.cpp   (contents, props changed)
   sandbox/chrono/libs/thread/src/win32/timeconv.inl   (contents, props changed)
   sandbox/chrono/libs/thread/src/win32/tss_dll.cpp   (contents, props changed)
   sandbox/chrono/libs/thread/src/win32/tss_pe.cpp   (contents, props changed)
Added: sandbox/chrono/libs/thread/src/pthread/once.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/pthread/once.cpp	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,51 @@
+// Copyright (C) 2007 Anthony Williams
+//
+//  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)
+
+#define __STDC_CONSTANT_MACROS
+#include <boost/thread/once.hpp>
+#include <boost/assert.hpp>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace boost
+{
+    namespace detail
+    {
+        BOOST_THREAD_DECL boost::uintmax_t once_global_epoch=UINTMAX_C(~0);
+        BOOST_THREAD_DECL pthread_mutex_t once_epoch_mutex=PTHREAD_MUTEX_INITIALIZER;
+        BOOST_THREAD_DECL pthread_cond_t once_epoch_cv = PTHREAD_COND_INITIALIZER;
+
+        namespace
+        {
+            pthread_key_t epoch_tss_key;
+            pthread_once_t epoch_tss_key_flag=PTHREAD_ONCE_INIT;
+            
+            extern "C" void delete_epoch_tss_data(void* data)
+            {
+                free(data);
+            }
+
+            extern "C" void create_epoch_tss_key()
+            {
+                BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
+            }
+            
+        }
+        
+        boost::uintmax_t& get_once_per_thread_epoch()
+        {
+            BOOST_VERIFY(!pthread_once(&epoch_tss_key_flag,create_epoch_tss_key));
+            void* data=pthread_getspecific(epoch_tss_key);
+            if(!data)
+            {
+                data=malloc(sizeof(boost::uintmax_t));
+                BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data));
+                *static_cast<boost::uintmax_t*>(data)=UINTMAX_C(~0);
+            }
+            return *static_cast<boost::uintmax_t*>(data);
+        }
+    }
+    
+}
Added: sandbox/chrono/libs/thread/src/pthread/thread.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/pthread/thread.cpp	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,607 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007-8 Anthony Williams
+//
+//  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)
+
+#include <boost/thread/detail/config.hpp>
+
+#include <boost/thread/thread.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/once.hpp>
+#include <boost/thread/tss.hpp>
+#include <boost/throw_exception.hpp>
+#ifdef __linux__
+#include <sys/sysinfo.h>
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#elif defined BOOST_HAS_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "timeconv.inl"
+
+namespace boost
+{
+    namespace detail
+    {
+        thread_data_base::~thread_data_base()
+        {}
+
+        struct thread_exit_callback_node
+        {
+            boost::detail::thread_exit_function_base* func;
+            thread_exit_callback_node* next;
+
+            thread_exit_callback_node(boost::detail::thread_exit_function_base* func_,
+                                      thread_exit_callback_node* next_):
+                func(func_),next(next_)
+            {}
+        };
+
+        namespace
+        {
+            boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
+            pthread_key_t current_thread_tls_key;
+
+            extern "C"
+            {
+                void tls_destructor(void* data)
+                {
+                    boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
+                    if(thread_info)
+                    {
+                        while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
+                        {
+                            while(thread_info->thread_exit_callbacks)
+                            {
+                                detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks;
+                                thread_info->thread_exit_callbacks=current_node->next;
+                                if(current_node->func)
+                                {
+                                    (*current_node->func)();
+                                    delete current_node->func;
+                                }
+                                delete current_node;
+                            }
+                            for(std::map<void const*,tss_data_node>::iterator next=thread_info->tss_data.begin(),
+                                    current,
+                                    end=thread_info->tss_data.end();
+                                next!=end;)
+                            {
+                                current=next;
+                                ++next;
+                                if(current->second.func && current->second.value)
+                                {
+                                    (*current->second.func)(current->second.value);
+                                }
+                                thread_info->tss_data.erase(current);
+                            }
+                        }
+                        thread_info->self.reset();
+                    }
+                }
+            }
+    
+
+            void create_current_thread_tls_key()
+            {
+                BOOST_VERIFY(!pthread_key_create(¤t_thread_tls_key,&tls_destructor));
+            }
+        }
+        
+        boost::detail::thread_data_base* get_current_thread_data()
+        {
+            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+            return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);
+        }
+
+        void set_current_thread_data(detail::thread_data_base* new_data)
+        {
+            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+            BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
+        }
+    }
+    
+    namespace
+    {
+        extern "C"
+        {
+            void* thread_proxy(void* param)
+            {
+                boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
+                thread_info->self.reset();
+                detail::set_current_thread_data(thread_info.get());
+                try
+                {
+                    thread_info->run();
+                }
+                catch(thread_interrupted const&)
+                {
+                }
+// Removed as it stops the debugger identifying the cause of the exception
+// Unhandled exceptions still cause the application to terminate
+//                 catch(...)
+//                 {
+//                     std::terminate();
+//                 }
+
+                detail::tls_destructor(thread_info.get());
+                detail::set_current_thread_data(0);
+                boost::lock_guard<boost::mutex> lock(thread_info->data_mutex);
+                thread_info->done=true;
+                thread_info->done_condition.notify_all();
+                return 0;
+            }
+        }
+
+        struct externally_launched_thread:
+            detail::thread_data_base
+        {
+            externally_launched_thread()
+            {
+                interrupt_enabled=false;
+            }
+            
+            void run()
+            {}
+
+        private:
+            externally_launched_thread(externally_launched_thread&);
+            void operator=(externally_launched_thread&);
+        };
+
+        detail::thread_data_base* make_external_thread_data()
+        {
+            detail::thread_data_base* const me(new externally_launched_thread());
+            me->self.reset(me);
+            set_current_thread_data(me);
+            return me;
+        }
+
+
+        detail::thread_data_base* get_or_make_current_thread_data()
+        {
+            detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
+            if(!current_thread_data)
+            {
+                current_thread_data=make_external_thread_data();
+            }
+            return current_thread_data;
+        }
+
+    }
+
+
+    thread::thread()
+    {}
+
+    void thread::start_thread()
+    {
+        thread_info->self=thread_info;
+        int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get());
+        if (res != 0)
+        {
+            thread_info->self.reset();
+            boost::throw_exception(thread_resource_error());
+        }
+    }
+
+    thread::~thread()
+    {
+        detach();
+    }
+
+    detail::thread_data_ptr thread::get_thread_info() const
+    {
+        lock_guard<mutex> l(thread_info_mutex);
+        return thread_info;
+    }
+
+    void thread::join()
+    {
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            bool do_join=false;
+            
+            {
+                unique_lock<mutex> lock(local_thread_info->data_mutex);
+                while(!local_thread_info->done)
+                {
+                    local_thread_info->done_condition.wait(lock);
+                }
+                do_join=!local_thread_info->join_started;
+                
+                if(do_join)
+                {
+                    local_thread_info->join_started=true;
+                }
+                else
+                {
+                    while(!local_thread_info->joined)
+                    {
+                        local_thread_info->done_condition.wait(lock);
+                    }
+                }
+            }
+            if(do_join)
+            {
+                void* result=0;
+                BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result));
+                lock_guard<mutex> lock(local_thread_info->data_mutex);
+                local_thread_info->joined=true;
+                local_thread_info->done_condition.notify_all();
+            }
+            
+            lock_guard<mutex> l1(thread_info_mutex);
+            if(thread_info==local_thread_info)
+            {
+                thread_info.reset();
+            }
+        }
+    }
+
+    bool thread::timed_join(system_time const& wait_until)
+    {
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            bool do_join=false;
+            
+            {
+                unique_lock<mutex> lock(local_thread_info->data_mutex);
+                while(!local_thread_info->done)
+                {
+                    if(!local_thread_info->done_condition.timed_wait(lock,wait_until))
+                    {
+                        return false;
+                    }
+                }
+                do_join=!local_thread_info->join_started;
+                
+                if(do_join)
+                {
+                    local_thread_info->join_started=true;
+                }
+                else
+                {
+                    while(!local_thread_info->joined)
+                    {
+                        local_thread_info->done_condition.wait(lock);
+                    }
+                }
+            }
+            if(do_join)
+            {
+                void* result=0;
+                BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result));
+                lock_guard<mutex> lock(local_thread_info->data_mutex);
+                local_thread_info->joined=true;
+                local_thread_info->done_condition.notify_all();
+            }
+            
+            lock_guard<mutex> l1(thread_info_mutex);
+            if(thread_info==local_thread_info)
+            {
+                thread_info.reset();
+            }
+        }
+        return true;
+    }
+
+    bool thread::joinable() const
+    {
+        return get_thread_info();
+    }
+
+
+    void thread::detach()
+    {
+        detail::thread_data_ptr local_thread_info;
+        {
+            lock_guard<mutex> l1(thread_info_mutex);
+            thread_info.swap(local_thread_info);
+        }
+        
+        if(local_thread_info)
+        {
+            lock_guard<mutex> lock(local_thread_info->data_mutex);
+            if(!local_thread_info->join_started)
+            {
+                BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle));
+                local_thread_info->join_started=true;
+                local_thread_info->joined=true;
+            }
+        }
+    }
+
+    namespace this_thread
+    {
+        
+        void sleep(const system_time& st)
+        {
+            detail::thread_data_base* const thread_info=detail::get_current_thread_data();
+        
+            if(thread_info)
+            {
+                unique_lock<mutex> lk(thread_info->sleep_mutex);
+                while(thread_info->sleep_condition.timed_wait(lk,st));
+            }
+            else
+            {
+                xtime const xt=get_xtime(st);
+            
+                for (int foo=0; foo < 5; ++foo)
+                {
+#   if defined(BOOST_HAS_PTHREAD_DELAY_NP)
+                    timespec ts;
+                    to_timespec_duration(xt, ts);
+                    BOOST_VERIFY(!pthread_delay_np(&ts));
+#   elif defined(BOOST_HAS_NANOSLEEP)
+                    timespec ts;
+                    to_timespec_duration(xt, ts);
+                
+                    //  nanosleep takes a timespec that is an offset, not
+                    //  an absolute time.
+                    nanosleep(&ts, 0);
+#   else
+                    mutex mx;
+                    mutex::scoped_lock lock(mx);
+                    condition cond;
+                    cond.timed_wait(lock, xt);
+#   endif
+                    xtime cur;
+                    xtime_get(&cur, TIME_UTC);
+                    if (xtime_cmp(xt, cur) <= 0)
+                        return;
+                }
+            }
+        }
+
+        void yield()
+        {
+#   if defined(BOOST_HAS_SCHED_YIELD)
+            BOOST_VERIFY(!sched_yield());
+#   elif defined(BOOST_HAS_PTHREAD_YIELD)
+            BOOST_VERIFY(!pthread_yield());
+#   else
+            xtime xt;
+            xtime_get(&xt, TIME_UTC);
+            sleep(xt);
+#   endif
+        }
+    }
+
+    unsigned thread::hardware_concurrency()
+    {
+#if defined(PTW32_VERSION) || defined(__hpux)
+        return pthread_num_processors_np();
+#elif defined(_GNU_SOURCE)
+        return get_nprocs();
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+        int count;
+        size_t size=sizeof(count);
+        return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
+#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
+        int const count=sysconf(_SC_NPROCESSORS_ONLN);
+        return (count>0)?count:0;
+#else
+        return 0;
+#endif
+    }
+
+    thread::id thread::get_id() const
+    {
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            return id(local_thread_info);
+        }
+        else
+        {
+            return id();
+        }
+    }
+
+    void thread::interrupt()
+    {
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            lock_guard<mutex> lk(local_thread_info->data_mutex);
+            local_thread_info->interrupt_requested=true;
+            if(local_thread_info->current_cond)
+            {
+                BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
+            }
+        }
+    }
+
+    bool thread::interruption_requested() const
+    {
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            lock_guard<mutex> lk(local_thread_info->data_mutex);
+            return local_thread_info->interrupt_requested;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    thread::native_handle_type thread::native_handle()
+    {
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            lock_guard<mutex> lk(local_thread_info->data_mutex);
+            return local_thread_info->thread_handle;
+        }
+        else
+        {
+            return pthread_t();
+        }
+    }
+    
+    
+
+    namespace this_thread
+    {
+        thread::id get_id()
+        {
+            boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
+            return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
+        }
+
+        void interruption_point()
+        {
+            boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
+            if(thread_info && thread_info->interrupt_enabled)
+            {
+                lock_guard<mutex> lg(thread_info->data_mutex);
+                if(thread_info->interrupt_requested)
+                {
+                    thread_info->interrupt_requested=false;
+                    throw thread_interrupted();
+                }
+            }
+        }
+        
+        bool interruption_enabled()
+        {
+            boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
+            return thread_info && thread_info->interrupt_enabled;
+        }
+        
+        bool interruption_requested()
+        {
+            boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
+            if(!thread_info)
+            {
+                return false;
+            }
+            else
+            {
+                lock_guard<mutex> lg(thread_info->data_mutex);
+                return thread_info->interrupt_requested;
+            }
+        }
+
+        disable_interruption::disable_interruption():
+            interruption_was_enabled(interruption_enabled())
+        {
+            if(interruption_was_enabled)
+            {
+                detail::get_current_thread_data()->interrupt_enabled=false;
+            }
+        }
+        
+        disable_interruption::~disable_interruption()
+        {
+            if(detail::get_current_thread_data())
+            {
+                detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled;
+            }
+        }
+
+        restore_interruption::restore_interruption(disable_interruption& d)
+        {
+            if(d.interruption_was_enabled)
+            {
+                detail::get_current_thread_data()->interrupt_enabled=true;
+            }
+        }
+        
+        restore_interruption::~restore_interruption()
+        {
+            if(detail::get_current_thread_data())
+            {
+                detail::get_current_thread_data()->interrupt_enabled=false;
+            }
+        }
+    }
+
+    namespace detail
+    {
+        void add_thread_exit_function(thread_exit_function_base* func)
+        {
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+            thread_exit_callback_node* const new_node=
+                new thread_exit_callback_node(func,current_thread_data->thread_exit_callbacks);
+            current_thread_data->thread_exit_callbacks=new_node;
+        }
+
+        tss_data_node* find_tss_data(void const* key)
+        {
+            detail::thread_data_base* const current_thread_data(get_current_thread_data());
+            if(current_thread_data)
+            {
+                std::map<void const*,tss_data_node>::iterator current_node=
+                    current_thread_data->tss_data.find(key);
+                if(current_node!=current_thread_data->tss_data.end())
+                {
+                    return ¤t_node->second;
+                }
+            }
+            return NULL;
+        }
+
+        void* get_tss_data(void const* key)
+        {
+            if(tss_data_node* const current_node=find_tss_data(key))
+            {
+                return current_node->value;
+            }
+            return NULL;
+        }
+
+        void add_new_tss_node(void const* key,
+                              boost::shared_ptr<tss_cleanup_function> func,
+                              void* tss_data)
+        {
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+            current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
+        }
+
+        void erase_tss_node(void const* key)
+        {
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+            current_thread_data->tss_data.erase(key);
+        }
+        
+        void set_tss_data(void const* key,
+                          boost::shared_ptr<tss_cleanup_function> func,
+                          void* tss_data,bool cleanup_existing)
+        {
+            if(tss_data_node* const current_node=find_tss_data(key))
+            {
+                if(cleanup_existing && current_node->func && current_node->value)
+                {
+                    (*current_node->func)(current_node->value);
+                }
+                if(func || tss_data)
+                {
+                    current_node->func=func;
+                    current_node->value=tss_data;
+                }
+                else
+                {
+                    erase_tss_node(key);
+                }
+            }
+            else
+            {
+                add_new_tss_node(key,func,tss_data);
+            }
+        }
+    }
+
+
+}
Added: sandbox/chrono/libs/thread/src/pthread/timeconv.inl
==============================================================================
Binary file. No diff available.
Added: sandbox/chrono/libs/thread/src/tss_null.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/tss_null.cpp	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,34 @@
+// (C) Copyright Michael Glassford 2004.
+// (C) Copyright 2007 Anthony Williams
+// 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/thread/detail/config.hpp>
+
+#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
+
+    /*
+    This file is a "null" implementation of tss cleanup; it's
+    purpose is to to eliminate link errors in cases
+    where it is known that tss cleanup is not needed.
+    */
+
+    extern "C" void tss_cleanup_implemented(void)
+    {
+        /*
+        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.
+        */
+    }
+
+#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)
Added: sandbox/chrono/libs/thread/src/win32/thread.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/win32/thread.cpp	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,598 @@
+// 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 2007 Anthony Williams
+// (C) Copyright 2007 David Deakins
+
+#define _WIN32_WINNT 0x400
+#define WINVER 0x400
+
+#include <boost/thread/thread.hpp>
+#include <algorithm>
+#include <windows.h>
+#ifndef UNDER_CE
+#include <process.h>
+#endif
+#include <stdio.h>
+#include <boost/thread/once.hpp>
+#include <boost/thread/tss.hpp>
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/thread/detail/tss_hooks.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
+
+namespace boost
+{
+    namespace
+    {
+        boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
+        DWORD current_thread_tls_key=0;
+
+        void create_current_thread_tls_key()
+        {
+            tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
+            current_thread_tls_key=TlsAlloc();
+            BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
+        }
+
+        void cleanup_tls_key()
+        {
+            if(current_thread_tls_key)
+            {
+                TlsFree(current_thread_tls_key);
+                current_thread_tls_key=0;
+            }
+        }
+
+        detail::thread_data_base* get_current_thread_data()
+        {
+            if(!current_thread_tls_key)
+            {
+                return 0;
+            }
+            return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
+        }
+
+        void set_current_thread_data(detail::thread_data_base* new_data)
+        {
+            boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+            BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data));
+        }
+
+#ifdef BOOST_NO_THREADEX
+// Windows CE doesn't define _beginthreadex
+
+        struct ThreadProxyData
+        {
+            typedef unsigned (__stdcall* func)(void*);
+            func start_address_;
+            void* arglist_;
+            ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {}
+        };
+
+        DWORD WINAPI ThreadProxy(LPVOID args)
+        {
+            ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
+            DWORD ret=data->start_address_(data->arglist_);
+            delete data;
+            return ret;
+        }
+        
+        typedef void* uintptr_t;
+
+        inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
+                                              void* arglist, unsigned initflag, unsigned* thrdaddr)
+        {
+            DWORD threadID;
+            HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
+                                        new ThreadProxyData(start_address,arglist),initflag,&threadID);
+            if (hthread!=0)
+                *thrdaddr=threadID;
+            return reinterpret_cast<uintptr_t const>(hthread);
+        }
+
+#endif
+
+    }
+
+    namespace detail
+    {
+        struct thread_exit_callback_node
+        {
+            boost::detail::thread_exit_function_base* func;
+            thread_exit_callback_node* next;
+
+            thread_exit_callback_node(boost::detail::thread_exit_function_base* func_,
+                                      thread_exit_callback_node* next_):
+                func(func_),next(next_)
+            {}
+        };
+
+        struct tss_data_node
+        {
+            void const* key;
+            boost::shared_ptr<boost::detail::tss_cleanup_function> func;
+            void* value;
+            tss_data_node* next;
+
+            tss_data_node(void const* key_,boost::shared_ptr<boost::detail::tss_cleanup_function> func_,void* value_,
+                          tss_data_node* next_):
+                key(key_),func(func_),value(value_),next(next_)
+            {}
+        };
+
+    }
+
+    namespace
+    {
+        void run_thread_exit_callbacks()
+        {
+            detail::thread_data_ptr current_thread_data(get_current_thread_data(),false);
+            if(current_thread_data)
+            {
+                while(current_thread_data->tss_data || current_thread_data->thread_exit_callbacks)
+                {
+                    while(current_thread_data->thread_exit_callbacks)
+                    {
+                        detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks;
+                        current_thread_data->thread_exit_callbacks=current_node->next;
+                        if(current_node->func)
+                        {
+                            (*current_node->func)();
+                            boost::detail::heap_delete(current_node->func);
+                        }
+                        boost::detail::heap_delete(current_node);
+                    }
+                    while(current_thread_data->tss_data)
+                    {
+                        detail::tss_data_node* const current_node=current_thread_data->tss_data;
+                        current_thread_data->tss_data=current_node->next;
+                        if(current_node->func)
+                        {
+                            (*current_node->func)(current_node->value);
+                        }
+                        boost::detail::heap_delete(current_node);
+                    }
+                }
+                
+                set_current_thread_data(0);
+            }
+        }
+        
+        unsigned __stdcall thread_start_function(void* param)
+        {
+            detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
+            set_current_thread_data(thread_info);
+            try
+            {
+                thread_info->run();
+            }
+            catch(thread_interrupted const&)
+            {
+            }
+// Removed as it stops the debugger identifying the cause of the exception
+// Unhandled exceptions still cause the application to terminate
+//             catch(...)
+//             {
+//                 std::terminate();
+//             }
+            run_thread_exit_callbacks();
+            return 0;
+        }
+    }
+
+    thread::thread()
+    {}
+
+    void thread::start_thread()
+    {
+        uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
+        if(!new_thread)
+        {
+            boost::throw_exception(thread_resource_error());
+        }
+        intrusive_ptr_add_ref(thread_info.get());
+        thread_info->thread_handle=(detail::win32::handle)(new_thread);
+        ResumeThread(thread_info->thread_handle);
+    }
+
+    thread::thread(detail::thread_data_ptr data):
+        thread_info(data)
+    {}
+
+    namespace
+    {
+        struct externally_launched_thread:
+            detail::thread_data_base
+        {
+            externally_launched_thread()
+            {
+                ++count;
+                interruption_enabled=false;
+            }
+            
+            void run()
+            {}
+        private:
+            externally_launched_thread(externally_launched_thread&);
+            void operator=(externally_launched_thread&);
+        };
+
+        void make_external_thread_data()
+        {
+            externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
+            set_current_thread_data(me);
+        }
+
+        detail::thread_data_base* get_or_make_current_thread_data()
+        {
+            detail::thread_data_base* current_thread_data(get_current_thread_data());
+            if(!current_thread_data)
+            {
+                make_external_thread_data();
+                current_thread_data=get_current_thread_data();
+            }
+            return current_thread_data;
+        }
+        
+    }
+
+    thread::~thread()
+    {
+        detach();
+    }
+    
+    thread::id thread::get_id() const
+    {
+        return thread::id(get_thread_info());
+    }
+
+    bool thread::joinable() const
+    {
+        return get_thread_info();
+    }
+
+    void thread::join()
+    {
+        detail::thread_data_ptr local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel());
+            release_handle();
+        }
+    }
+
+    bool thread::timed_join(boost::system_time const& wait_until)
+    {
+        detail::thread_data_ptr local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            if(!this_thread::interruptible_wait(local_thread_info->thread_handle,get_milliseconds_until(wait_until)))
+            {
+                return false;
+            }
+            release_handle();
+        }
+        return true;
+    }
+    
+    void thread::detach()
+    {
+        release_handle();
+    }
+
+    void thread::release_handle()
+    {
+        lock_guard<mutex> l1(thread_info_mutex);
+        thread_info=0;
+    }
+    
+    void thread::interrupt()
+    {
+        detail::thread_data_ptr local_thread_info=get_thread_info();
+        if(local_thread_info)
+        {
+            local_thread_info->interrupt();
+        }
+    }
+    
+    bool thread::interruption_requested() const
+    {
+        detail::thread_data_ptr local_thread_info=get_thread_info();
+        return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0);
+    }
+    
+    unsigned thread::hardware_concurrency()
+    {
+        SYSTEM_INFO info={0};
+        GetSystemInfo(&info);
+        return info.dwNumberOfProcessors;
+    }
+    
+    thread::native_handle_type thread::native_handle()
+    {
+        detail::thread_data_ptr local_thread_info=get_thread_info();
+        return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
+    }
+
+    detail::thread_data_ptr thread::get_thread_info() const
+    {
+        boost::mutex::scoped_lock l(thread_info_mutex);
+        return thread_info;
+    }
+
+    namespace this_thread
+    {
+        namespace
+        {
+            LARGE_INTEGER get_due_time(detail::timeout const&  target_time)
+            {
+                LARGE_INTEGER due_time={0};
+                if(target_time.relative)
+                {
+                    unsigned long const elapsed_milliseconds=GetTickCount()-target_time.start;
+                    LONGLONG const remaining_milliseconds=(target_time.milliseconds-elapsed_milliseconds);
+                    LONGLONG const hundred_nanoseconds_in_one_millisecond=10000;
+
+                    if(remaining_milliseconds>0)
+                    {
+                        due_time.QuadPart=-(remaining_milliseconds*hundred_nanoseconds_in_one_millisecond);
+                    }
+                }
+                else
+                {
+                    SYSTEMTIME target_system_time={0};
+                    target_system_time.wYear=target_time.abs_time.date().year();
+                    target_system_time.wMonth=target_time.abs_time.date().month();
+                    target_system_time.wDay=target_time.abs_time.date().day();
+                    target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours();
+                    target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes();
+                    target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds();
+
+                    if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time)))
+                    {
+                        due_time.QuadPart=0;
+                    }
+                    else
+                    {
+                        long const hundred_nanoseconds_in_one_second=10000000;
+                        due_time.QuadPart+=target_time.abs_time.time_of_day().fractional_seconds()*(hundred_nanoseconds_in_one_second/target_time.abs_time.time_of_day().ticks_per_second());
+                    }
+                }
+                return due_time;
+            }
+        }
+        
+
+        bool interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time)
+        {
+            detail::win32::handle handles[3]={0};
+            unsigned handle_count=0;
+            unsigned wait_handle_index=~0U;
+            unsigned interruption_index=~0U;
+            unsigned timeout_index=~0U;
+            if(handle_to_wait_for!=detail::win32::invalid_handle_value)
+            {
+                wait_handle_index=handle_count;
+                handles[handle_count++]=handle_to_wait_for;
+            }
+            if(get_current_thread_data() && get_current_thread_data()->interruption_enabled)
+            {
+                interruption_index=handle_count;
+                handles[handle_count++]=get_current_thread_data()->interruption_handle;
+            }
+
+            detail::win32::handle_manager timer_handle;
+            
+#ifndef UNDER_CE
+            unsigned const min_timer_wait_period=20;
+            
+            if(!target_time.is_sentinel())
+            {
+                detail::timeout::remaining_time const time_left=target_time.remaining_milliseconds();
+                if(time_left.milliseconds > min_timer_wait_period)
+                {
+                    // for a long-enough timeout, use a waitable timer (which tracks clock changes)
+                    timer_handle=CreateWaitableTimer(NULL,false,NULL);
+                    if(timer_handle!=0)
+                    {
+                        LARGE_INTEGER due_time=get_due_time(target_time);
+                        
+                        bool const set_time_succeeded=SetWaitableTimer(timer_handle,&due_time,0,0,0,false)!=0;
+                        if(set_time_succeeded)
+                        {
+                            timeout_index=handle_count;
+                            handles[handle_count++]=timer_handle;
+                        }
+                    }
+                }
+                else if(!target_time.relative)
+                {
+                    // convert short absolute-time timeouts into relative ones, so we don't race against clock changes
+                    target_time=detail::timeout(time_left.milliseconds);
+                }
+            }
+#endif
+        
+            bool const using_timer=timeout_index!=~0u;
+            detail::timeout::remaining_time time_left(0);
+            
+            do
+            {
+                if(!using_timer)
+                {
+                    time_left=target_time.remaining_milliseconds();
+                }
+                
+                if(handle_count)
+                {
+                    unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds);
+                    if(notified_index<handle_count)
+                    {
+                        if(notified_index==wait_handle_index)
+                        {
+                            return true;
+                        }
+                        else if(notified_index==interruption_index)
+                        {
+                            detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
+                            throw thread_interrupted();
+                        }
+                        else if(notified_index==timeout_index)
+                        {
+                            return false;
+                        }
+                    }
+                }
+                else
+                {
+                    detail::win32::Sleep(time_left.milliseconds);
+                }
+                if(target_time.relative)
+                {
+                    target_time.milliseconds-=detail::timeout::max_non_infinite_wait;
+                }
+            }
+            while(time_left.more);
+            return false;
+        }
+
+        thread::id get_id()
+        {
+            return thread::id(get_or_make_current_thread_data());
+        }
+
+        void interruption_point()
+        {
+            if(interruption_enabled() && interruption_requested())
+            {
+                detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
+                throw thread_interrupted();
+            }
+        }
+        
+        bool interruption_enabled()
+        {
+            return get_current_thread_data() && get_current_thread_data()->interruption_enabled;
+        }
+        
+        bool interruption_requested()
+        {
+            return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0);
+        }
+
+        void yield()
+        {
+            detail::win32::Sleep(0);
+        }
+        
+        disable_interruption::disable_interruption():
+            interruption_was_enabled(interruption_enabled())
+        {
+            if(interruption_was_enabled)
+            {
+                get_current_thread_data()->interruption_enabled=false;
+            }
+        }
+        
+        disable_interruption::~disable_interruption()
+        {
+            if(get_current_thread_data())
+            {
+                get_current_thread_data()->interruption_enabled=interruption_was_enabled;
+            }
+        }
+
+        restore_interruption::restore_interruption(disable_interruption& d)
+        {
+            if(d.interruption_was_enabled)
+            {
+                get_current_thread_data()->interruption_enabled=true;
+            }
+        }
+        
+        restore_interruption::~restore_interruption()
+        {
+            if(get_current_thread_data())
+            {
+                get_current_thread_data()->interruption_enabled=false;
+            }
+        }
+    }
+
+    namespace detail
+    {
+        void add_thread_exit_function(thread_exit_function_base* func)
+        {
+            detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+            thread_exit_callback_node* const new_node=
+                heap_new<thread_exit_callback_node>(func,
+                                                    current_thread_data->thread_exit_callbacks);
+            current_thread_data->thread_exit_callbacks=new_node;
+        }
+
+        tss_data_node* find_tss_data(void const* key)
+        {
+            detail::thread_data_base* const current_thread_data(get_current_thread_data());
+            if(current_thread_data)
+            {
+                detail::tss_data_node* current_node=current_thread_data->tss_data;
+                while(current_node)
+                {
+                    if(current_node->key==key)
+                    {
+                        return current_node;
+                    }
+                    current_node=current_node->next;
+                }
+            }
+            return NULL;
+        }
+
+        void* get_tss_data(void const* key)
+        {
+            if(tss_data_node* const current_node=find_tss_data(key))
+            {
+                return current_node->value;
+            }
+            return NULL;
+        }
+        
+        void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing)
+        {
+            if(tss_data_node* const current_node=find_tss_data(key))
+            {
+                if(cleanup_existing && current_node->func.get() && current_node->value)
+                {
+                    (*current_node->func)(current_node->value);
+                }
+                current_node->func=func;
+                current_node->value=tss_data;
+            }
+            else
+            {
+                detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
+                tss_data_node* const new_node=heap_new<tss_data_node>(key,func,tss_data,current_thread_data->tss_data);
+                current_thread_data->tss_data=new_node;
+            }
+        }
+    }
+}
+
+
+extern "C" BOOST_THREAD_DECL void on_process_enter()
+{}
+
+extern "C" BOOST_THREAD_DECL void on_thread_enter()
+{}
+
+extern "C" BOOST_THREAD_DECL void on_process_exit()
+{
+    boost::cleanup_tls_key();
+}
+
+extern "C" BOOST_THREAD_DECL void on_thread_exit()
+{
+    boost::run_thread_exit_callbacks();
+}
+
Added: sandbox/chrono/libs/thread/src/win32/timeconv.inl
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/win32/timeconv.inl	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,130 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+//
+//  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)
+
+// boostinspect:nounnamed
+
+namespace {
+const int MILLISECONDS_PER_SECOND = 1000;
+const int NANOSECONDS_PER_SECOND = 1000000000;
+const int NANOSECONDS_PER_MILLISECOND = 1000000;
+
+const int MICROSECONDS_PER_SECOND = 1000000;
+const int NANOSECONDS_PER_MICROSECOND = 1000;
+
+inline void to_time(int milliseconds, boost::xtime& xt)
+{
+    int res = 0;
+    res = boost::xtime_get(&xt, boost::TIME_UTC);
+    assert(res == boost::TIME_UTC);
+
+    xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
+    xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
+        NANOSECONDS_PER_MILLISECOND);
+
+    if (xt.nsec >= NANOSECONDS_PER_SECOND)
+    {
+        ++xt.sec;
+        xt.nsec -= NANOSECONDS_PER_SECOND;
+    }
+}
+
+#if defined(BOOST_HAS_PTHREADS)
+inline void to_timespec(const boost::xtime& xt, timespec& ts)
+{
+    ts.tv_sec = static_cast<int>(xt.sec);
+    ts.tv_nsec = static_cast<int>(xt.nsec);
+    if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
+    {
+        ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
+        ts.tv_nsec %= NANOSECONDS_PER_SECOND;
+    }
+}
+
+inline void to_time(int milliseconds, timespec& ts)
+{
+    boost::xtime xt;
+    to_time(milliseconds, xt);
+    to_timespec(xt, ts);
+}
+
+inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
+{
+    boost::xtime cur;
+    int res = 0;
+    res = boost::xtime_get(&cur, boost::TIME_UTC);
+    assert(res == boost::TIME_UTC);
+
+    if (boost::xtime_cmp(xt, cur) <= 0)
+    {
+        ts.tv_sec = 0;
+        ts.tv_nsec = 0;
+    }
+    else
+    {
+        ts.tv_sec = xt.sec - cur.sec;
+        ts.tv_nsec = xt.nsec - cur.nsec;
+
+        if( ts.tv_nsec < 0 )
+        {
+            ts.tv_sec -= 1;
+            ts.tv_nsec += NANOSECONDS_PER_SECOND;
+        }
+        if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
+        {
+            ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
+            ts.tv_nsec %= NANOSECONDS_PER_SECOND;
+        }
+    }
+}
+#endif
+
+inline void to_duration(boost::xtime xt, int& milliseconds)
+{
+    boost::xtime cur;
+    int res = 0;
+    res = boost::xtime_get(&cur, boost::TIME_UTC);
+    assert(res == boost::TIME_UTC);
+
+    if (boost::xtime_cmp(xt, cur) <= 0)
+        milliseconds = 0;
+    else
+    {
+        if (cur.nsec > xt.nsec)
+        {
+            xt.nsec += NANOSECONDS_PER_SECOND;
+            --xt.sec;
+        }
+        milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
+            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
+                NANOSECONDS_PER_MILLISECOND);
+    }
+}
+
+inline void to_microduration(boost::xtime xt, int& microseconds)
+{
+    boost::xtime cur;
+    int res = 0;
+    res = boost::xtime_get(&cur, boost::TIME_UTC);
+    assert(res == boost::TIME_UTC);
+
+    if (boost::xtime_cmp(xt, cur) <= 0)
+        microseconds = 0;
+    else
+    {
+        if (cur.nsec > xt.nsec)
+        {
+            xt.nsec += NANOSECONDS_PER_SECOND;
+            --xt.sec;
+        }
+        microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
+            (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
+                NANOSECONDS_PER_MICROSECOND);
+    }
+}
+}
+
+// Change Log:
+//    1 Jun 01  Initial creation.
Added: sandbox/chrono/libs/thread/src/win32/tss_dll.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/win32/tss_dll.cpp	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,72 @@
+// (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/thread/detail/config.hpp>
+
+#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
+
+    #include <boost/thread/detail/tss_hooks.hpp>
+
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+
+    #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:
+            {
+                on_process_enter();
+                on_thread_enter();
+                break;
+            }
+
+            case DLL_THREAD_ATTACH:
+            {
+                on_thread_enter();
+                break;
+            }
+
+            case DLL_THREAD_DETACH:
+            {
+                on_thread_exit();
+                break;
+            }
+
+            case DLL_PROCESS_DETACH:
+            {
+                on_thread_exit();
+                on_process_exit();
+                break;
+            }
+        }
+
+        return TRUE;
+    }
+
+    extern "C" void tss_cleanup_implemented(void)
+    {
+        /*
+        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.
+        */
+    }
+
+#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
Added: sandbox/chrono/libs/thread/src/win32/tss_pe.cpp
==============================================================================
--- (empty file)
+++ sandbox/chrono/libs/thread/src/win32/tss_pe.cpp	2010-05-20 03:47:55 EDT (Thu, 20 May 2010)
@@ -0,0 +1,287 @@
+// $Id: tss_pe.cpp 49324 2008-10-13 20:30:13Z anthonyw $
+// (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/thread/detail/config.hpp>
+
+#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) 
+
+#if defined(__MINGW32__) && !defined(_WIN64)
+
+#include <boost/thread/detail/tss_hooks.hpp>
+
+#include <windows.h>
+
+#include <cstdlib>
+
+extern "C" void tss_cleanup_implemented(void) {}
+
+namespace {
+    void NTAPI on_tls_callback(void* h, DWORD dwReason, PVOID pv)
+    {
+        switch (dwReason)
+        {
+        case DLL_THREAD_DETACH:
+        {
+            on_thread_exit();
+            break;
+        }
+        }
+    }
+
+    void on_after_ctors(void)
+    {
+        on_process_enter();
+    }
+    
+    void on_before_dtors(void)
+    {
+        on_thread_exit();
+    }
+    
+    void on_after_dtors(void)
+    {
+        on_process_exit();        
+    }
+}
+
+extern "C" {
+
+    void (* after_ctors )(void) __attribute__((section(".ctors")))     = on_after_ctors;
+    void (* before_dtors)(void) __attribute__((section(".dtors")))     = on_before_dtors;
+    void (* after_dtors )(void) __attribute__((section(".dtors.zzz"))) = on_after_dtors;
+
+    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_tls_callback__ __attribute__ ((section(".CRT$XLB"))) = on_tls_callback;
+    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
+};
+
+
+#elif  defined(_MSC_VER) && !defined(UNDER_CE)
+
+    #include <boost/thread/detail/tss_hooks.hpp>
+
+    #include <stdlib.h>
+
+    #define WIN32_LEAN_AND_MEAN
+    #include <windows.h>
+
+    //Definitions required by implementation
+
+    #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
+        typedef void (__cdecl *_PVFV)(void);
+        #define INIRETSUCCESS
+        #define PVAPI void
+    #else
+        typedef int (__cdecl *_PVFV)(void);
+        #define INIRETSUCCESS 0
+        #define PVAPI int
+    #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(void);
+        static PVAPI on_process_init(void);
+        static PVAPI on_process_term(void);
+        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(void)
+        {
+            //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(void)
+        {
+            //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(on_thread_exit);
+
+            //Call Boost process entry callback here
+
+            on_process_enter();
+
+            return INIRETSUCCESS;
+        }
+
+        PVAPI on_process_term(void)
+        {
+            on_process_exit();
+            return INIRETSUCCESS;
+        }
+
+        void NTAPI on_tls_callback(HINSTANCE /*h*/, DWORD dwReason, PVOID /*pv*/)
+        {
+            switch (dwReason)
+            {
+            case DLL_THREAD_DETACH:
+                on_thread_exit();
+                break;
+            }
+        }
+
+        BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID)
+        {
+            switch (dwReason)
+            {
+            case DLL_THREAD_DETACH:
+                on_thread_exit();
+                break;
+            case DLL_PROCESS_DETACH:
+                on_process_exit();
+                break;
+            }
+            return true;
+        }
+    } //namespace
+
+extern "C"
+{
+    extern BOOL (WINAPI * const _pRawDllMain)(HANDLE, DWORD, LPVOID)=&dll_callback;
+}
+
+    extern "C" void tss_cleanup_implemented(void)
+    {
+        /*
+        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.
+        */
+    }
+#endif //defined(_MSC_VER) && !defined(UNDER_CE)
+
+#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)