+++ /dev/null
-## ---------------------------------------------------------------------
-## $Id$
-##
-## Copyright (C) 2012 - 2019 by the deal.II authors
-##
-## This file is part of the deal.II library.
-##
-## The deal.II library is free software; you can use it, redistribute
-## it, and/or modify it under the terms of the GNU Lesser General
-## Public License as published by the Free Software Foundation; either
-## version 2.1 of the License, or (at your option) any later version.
-## The full text of the license can be found in the file LICENSE.md at
-## the top level directory of deal.II.
-##
-## ---------------------------------------------------------------------
-
-if(DEAL_II_USE_MT_POSIX)
- set(src_boost_thread
- pthread/once.cpp
- pthread/thread.cpp
- )
-else()
- set(src_boost_thread
- win32/thread.cpp
- win32/tss_dll.cpp
- win32/tss_pe.cpp
- )
-endif()
-
-deal_ii_add_library(obj_boost_thread OBJECT ${src_boost_thread})
-deal_ii_add_definitions(obj_boost_thread
- "BOOST_THREAD_BUILD_LIB" "BOOST_ALL_NO_LIB"
- )
-
-if(CMAKE_SYSTEM_NAME MATCHES "Windows")
- deal_ii_add_definitions(obj_boost_thread "BOOST_HAS_WINTHREADS")
-else()
- deal_ii_add_definitions(obj_boost_thread "BOOST_THREAD_POSIX")
-endif()
-
+++ /dev/null
-// (C) Copyright 2012 Vicente J. Botet Escriba
-// 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>
-
-#ifndef BOOST_NO_EXCEPTIONS
-
-#include <boost/thread/futures/future_error_code.hpp>
-#include <string>
-
-namespace boost
-{
-
- namespace thread_detail
- {
-
- class future_error_category :
- public boost::system::error_category
- {
- public:
- virtual const char* name() const BOOST_NOEXCEPT;
- virtual std::string message(int ev) const;
- };
-
- const char*
- future_error_category::name() const BOOST_NOEXCEPT
- {
- return "future";
- }
-
- std::string
- future_error_category::message(int ev) const
- {
- switch (BOOST_SCOPED_ENUM_NATIVE(future_errc)(ev))
- {
- case future_errc::broken_promise:
- return std::string("The associated promise has been destructed prior "
- "to the associated state becoming ready.");
- case future_errc::future_already_retrieved:
- return std::string("The future has already been retrieved from "
- "the promise or packaged_task.");
- case future_errc::promise_already_satisfied:
- return std::string("The state of the promise has already been set.");
- case future_errc::no_state:
- return std::string("Operation not permitted on an object without "
- "an associated state.");
- }
- return std::string("unspecified future_errc value\n");
- }
- future_error_category future_error_category_var;
- }
-
- BOOST_THREAD_DECL
- const system::error_category&
- future_category() BOOST_NOEXCEPT
- {
- return thread_detail::future_error_category_var;
- }
-
-}
-#endif
-
+++ /dev/null
-// 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)
-
-#include <boost/thread/detail/config.hpp>
-#ifdef BOOST_THREAD_ONCE_ATOMIC
-#include "./once_atomic.cpp"
-#else
-#define __STDC_CONSTANT_MACROS
-#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
-#include <boost/thread/once.hpp>
-#include <boost/assert.hpp>
-#include <boost/throw_exception.hpp>
-#include <pthread.h>
-#include <stdlib.h>
-#include <memory>
-#include <string.h> // memcmp.
-namespace boost
-{
- namespace thread_detail
- {
- BOOST_THREAD_DECL uintmax_atomic_t once_global_epoch=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C;
- 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"
- {
- static void delete_epoch_tss_data(void* data)
- {
- free(data);
- }
-
- static void create_epoch_tss_key()
- {
- BOOST_VERIFY(!pthread_key_create(&epoch_tss_key,delete_epoch_tss_data));
- }
- }
-
-#if defined BOOST_THREAD_PATCH
- const pthread_once_t pthread_once_init_value=PTHREAD_ONCE_INIT;
- struct BOOST_THREAD_DECL delete_epoch_tss_key_on_dlclose_t
- {
- delete_epoch_tss_key_on_dlclose_t()
- {
- }
- ~delete_epoch_tss_key_on_dlclose_t()
- {
- if(memcmp(&epoch_tss_key_flag, &pthread_once_init_value, sizeof(pthread_once_t)))
- {
- void* data = pthread_getspecific(epoch_tss_key);
- if (data)
- delete_epoch_tss_data(data);
- pthread_key_delete(epoch_tss_key);
- }
- }
- };
- delete_epoch_tss_key_on_dlclose_t delete_epoch_tss_key_on_dlclose;
-#endif
- }
-
- uintmax_atomic_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(thread_detail::uintmax_atomic_t));
- if(!data) BOOST_THROW_EXCEPTION(std::bad_alloc());
- BOOST_VERIFY(!pthread_setspecific(epoch_tss_key,data));
- *static_cast<thread_detail::uintmax_atomic_t*>(data)=BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C;
- }
- return *static_cast<thread_detail::uintmax_atomic_t*>(data);
- }
- }
-
-}
-#endif //
+++ /dev/null
-// (C) Copyright 2013 Andrey Semashev
-// (C) Copyright 2013 Vicente J. Botet Escriba
-//
-// 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/detail/config.hpp>
-#include <boost/thread/once.hpp>
-#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
-#include <boost/assert.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/atomic.hpp>
-#include <boost/memory_order.hpp>
-#include <pthread.h>
-
-namespace boost
-{
- namespace thread_detail
- {
-
- enum flag_states
- {
- uninitialized, in_progress, initialized
- };
-
-
-#ifndef BOOST_THREAD_PROVIDES_ONCE_CXX11
- BOOST_STATIC_ASSERT_MSG(sizeof(atomic_int_type) == sizeof(atomic_type), "Boost.Thread: unsupported platform");
-#endif
-
- static pthread_mutex_t once_mutex = PTHREAD_MUTEX_INITIALIZER;
- static pthread_cond_t once_cv = PTHREAD_COND_INITIALIZER;
-
- BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT
- {
- atomic_type& f = get_atomic_storage(flag);
- if (f.load(memory_order_acquire) != initialized)
- {
- pthread::pthread_mutex_scoped_lock lk(&once_mutex);
- if (f.load(memory_order_acquire) != initialized)
- {
- for (;;)
- {
- atomic_int_type expected = uninitialized;
- if (f.compare_exchange_strong(expected, in_progress, memory_order_acq_rel, memory_order_acquire))
- {
- // We have set the flag to in_progress
- return true;
- }
- else if (expected == initialized)
- {
- // Another thread managed to complete the initialization
- return false;
- }
- else
- {
- // Wait until the initialization is complete
- //pthread::pthread_mutex_scoped_lock lk(&once_mutex);
- BOOST_VERIFY(!pthread_cond_wait(&once_cv, &once_mutex));
- }
- }
- }
- }
- return false;
- }
-
- BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT
- {
- atomic_type& f = get_atomic_storage(flag);
- {
- pthread::pthread_mutex_scoped_lock lk(&once_mutex);
- f.store(initialized, memory_order_release);
- }
- BOOST_VERIFY(!pthread_cond_broadcast(&once_cv));
- }
-
- BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT
- {
- atomic_type& f = get_atomic_storage(flag);
- {
- pthread::pthread_mutex_scoped_lock lk(&once_mutex);
- f.store(uninitialized, memory_order_release);
- }
- BOOST_VERIFY(!pthread_cond_broadcast(&once_cv));
- }
-
- } // namespace thread_detail
-
-} // namespace boost
+++ /dev/null
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2007-8 Anthony Williams
-// (C) Copyright 2011-2012 Vicente J. Botet Escriba
-//
-// 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_only.hpp>
-#if defined BOOST_THREAD_USES_DATETIME
-#include <boost/thread/xtime.hpp>
-#endif
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/once.hpp>
-#include <boost/thread/tss.hpp>
-#include <boost/thread/future.hpp>
-
-#ifdef __GLIBC__
-#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
-
-#if defined(__VXWORKS__)
-#include <vxCpuLib.h>
-#endif
-
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/trim.hpp>
-#include <boost/lexical_cast.hpp>
-
-#include <fstream>
-#include <string>
-#include <set>
-#include <vector>
-#include <string.h> // memcmp.
-
-namespace boost
-{
- namespace detail
- {
- thread_data_base::~thread_data_base()
- {
- for (notify_list_t::iterator i = notify.begin(), e = notify.end();
- i != e; ++i)
- {
- i->second->unlock();
- i->first->notify_all();
- }
-//#ifndef BOOST_NO_EXCEPTIONS
- for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
- i != e; ++i)
- {
- (*i)->notify_deferred();
- }
-//#endif
- }
-
- 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
- {
-#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
- boost::once_flag current_thread_tls_init_flag;
-#else
- boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
-#endif
- pthread_key_t current_thread_tls_key;
-
- extern "C"
- {
- static void tls_destructor(void* data)
- {
- //boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
- boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();
-
- 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;
- }
- while (!thread_info->tss_data.empty())
- {
- std::map<void const*,detail::tss_data_node>::iterator current
- = thread_info->tss_data.begin();
- if(current->second.func && (current->second.value!=0))
- {
- (*current->second.caller)(current->second.func,current->second.value);
- }
- thread_info->tss_data.erase(current);
- }
- }
- thread_info->self.reset();
- }
- }
- }
-
-#if defined BOOST_THREAD_PATCH
- struct delete_current_thread_tls_key_on_dlclose_t
- {
- delete_current_thread_tls_key_on_dlclose_t()
- {
- }
- ~delete_current_thread_tls_key_on_dlclose_t()
- {
- const boost::once_flag uninitialized = BOOST_ONCE_INIT;
- if (memcmp(¤t_thread_tls_init_flag, &uninitialized, sizeof(boost::once_flag)))
- {
- void* data = pthread_getspecific(current_thread_tls_key);
- if (data)
- tls_destructor(data);
- pthread_key_delete(current_thread_tls_key);
- }
- }
- };
- delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;
-#endif
- 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"
- {
- static void* thread_proxy(void* param)
- {
- //boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
- boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this();
- thread_info->self.reset();
- detail::set_current_thread_data(thread_info.get());
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- BOOST_TRY
- {
-#endif
- thread_info->run();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
-
- }
- BOOST_CATCH (thread_interrupted const&)
- {
- }
-// Removed as it stops the debugger identifying the cause of the exception
-// Unhandled exceptions still cause the application to terminate
-// BOOST_CATCH(...)
-// {
-// throw;
-//
-// std::terminate();
-// }
- BOOST_CATCH_END
-#endif
- 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;
- }
- }
- }
- namespace detail
- {
- struct externally_launched_thread:
- detail::thread_data_base
- {
- externally_launched_thread()
- {
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- interrupt_enabled=false;
-#endif
- }
- ~externally_launched_thread() {
- BOOST_ASSERT(notify.empty());
- notify.clear();
-//#ifndef BOOST_NO_EXCEPTIONS
- BOOST_ASSERT(async_states_.empty());
- async_states_.clear();
-//#endif
- }
- void run()
- {}
- void notify_all_at_thread_exit(condition_variable*, mutex*)
- {}
-
- private:
- externally_launched_thread(externally_launched_thread&);
- void operator=(externally_launched_thread&);
- };
-
- thread_data_base* make_external_thread_data()
- {
- thread_data_base* const me(detail::heap_new<externally_launched_thread>());
- me->self.reset(me);
- set_current_thread_data(me);
- return me;
- }
-
-
- thread_data_base* get_or_make_current_thread_data()
- {
- thread_data_base* current_thread_data(get_current_thread_data());
- if(!current_thread_data)
- {
- current_thread_data=make_external_thread_data();
- }
- return current_thread_data;
- }
-
- }
-
-
- thread::thread() BOOST_NOEXCEPT
- {}
-
- bool thread::start_thread_noexcept()
- {
- 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();
- return false;
- }
- return true;
- }
-
- bool thread::start_thread_noexcept(const attributes& attr)
- {
- thread_info->self=thread_info;
- const attributes::native_handle_type* h = attr.native_handle();
- int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get());
- if (res != 0)
- {
- thread_info->self.reset();
- return false;
- }
- int detached_state;
- res = pthread_attr_getdetachstate(h, &detached_state);
- if (res != 0)
- {
- thread_info->self.reset();
- return false;
- }
- if (PTHREAD_CREATE_DETACHED==detached_state)
- {
- detail::thread_data_ptr local_thread_info;
- 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;
- }
- }
- }
- return true;
- }
-
-
-
- detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
- {
- return thread_info;
- }
-
- bool thread::join_noexcept()
- {
- 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();
- }
-
- if(thread_info==local_thread_info)
- {
- thread_info.reset();
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-
- bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res)
- {
- 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.do_wait_until(lock,timeout)) break; // timeout occurred
- }
- if(!local_thread_info->done)
- {
- res=false;
- return true;
- }
- 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();
- }
-
- if(thread_info==local_thread_info)
- {
- thread_info.reset();
- }
- res=true;
- return true;
- }
- else
- {
- return false;
- }
- }
-
- bool thread::joinable() const BOOST_NOEXCEPT
- {
- return (get_thread_info)()?true:false;
- }
-
-
- void thread::detach()
- {
- detail::thread_data_ptr local_thread_info;
- 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
- {
- namespace no_interruption_point
- {
- namespace hidden
- {
- void BOOST_THREAD_DECL sleep_for_internal(const detail::platform_duration& ts)
- {
- if (ts > detail::platform_duration::zero())
- {
- // Use pthread_delay_np or nanosleep whenever possible here in the no_interruption_point
- // namespace because they do not provide an interruption point.
- # if defined(BOOST_HAS_PTHREAD_DELAY_NP)
- # if defined(__IBMCPP__) || defined(_AIX)
- BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts.getTs())));
- # else
- BOOST_VERIFY(!pthread_delay_np(&ts.getTs()));
- # endif
- # elif defined(BOOST_HAS_NANOSLEEP)
- nanosleep(&ts.getTs(), 0);
- # else
- // This should never be reached due to BOOST_THREAD_SLEEP_FOR_IS_STEADY
- # endif
- }
- }
- }
- }
-
- void yield() BOOST_NOEXCEPT
- {
-# if defined(BOOST_HAS_SCHED_YIELD)
- BOOST_VERIFY(!sched_yield());
-# elif defined(BOOST_HAS_PTHREAD_YIELD)
- BOOST_VERIFY(!pthread_yield());
-//# elif defined BOOST_THREAD_USES_DATETIME
-// ::boost::xtime xt;
-// xtime_get(&xt, TIME_UTC_);
-// sleep(xt);
-// sleep_for(chrono::milliseconds(0));
-# else
- mutex mx;
- unique_lock<mutex> lock(mx);
- condition_variable cond;
- cond.do_wait_until(lock, detail::internal_platform_clock::now());
-# endif
- }
- }
- unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
- {
-#if defined(PTW32_VERSION) || defined(__hpux)
- return pthread_num_processors_np();
-#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;
-#elif defined(__VXWORKS__)
- cpuset_t set = ::vxCpuEnabledGet();
- #ifdef __DCC__
- int i;
- for( i = 0; set; ++i)
- {
- set &= set -1;
- }
- return(i);
- #else
- return (__builtin_popcount(set) );
- #endif
-#elif defined(__GLIBC__)
- return get_nprocs();
-#else
- return 0;
-#endif
- }
-
- unsigned thread::physical_concurrency() BOOST_NOEXCEPT
- {
-#ifdef __linux__
- try {
- using namespace std;
-
- ifstream proc_cpuinfo ("/proc/cpuinfo");
-
- const string physical_id("physical id"), core_id("core id");
-
- typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id]
-
- std::set<core_entry> cores;
-
- core_entry current_core_entry;
-
- string line;
- while ( getline(proc_cpuinfo, line) ) {
- if (line.empty())
- continue;
-
- vector<string> key_val(2);
- boost::split(key_val, line, boost::is_any_of(":"));
-
- if (key_val.size() != 2)
- return hardware_concurrency();
-
- string key = key_val[0];
- string value = key_val[1];
- boost::trim(key);
- boost::trim(value);
-
- if (key == physical_id) {
- current_core_entry.first = boost::lexical_cast<unsigned>(value);
- continue;
- }
-
- if (key == core_id) {
- current_core_entry.second = boost::lexical_cast<unsigned>(value);
- cores.insert(current_core_entry);
- continue;
- }
- }
- // Fall back to hardware_concurrency() in case
- // /proc/cpuinfo is formatted differently than we expect.
- return cores.size() != 0 ? cores.size() : hardware_concurrency();
- } catch(...) {
- return hardware_concurrency();
- }
-#elif defined(__APPLE__)
- int count;
- size_t size=sizeof(count);
- return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count;
-#else
- return hardware_concurrency();
-#endif
- }
-
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- 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::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex);
- BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
- }
- }
- }
-
- bool thread::interruption_requested() const BOOST_NOEXCEPT
- {
- 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;
- }
- }
-#endif
-
- 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();
- }
- }
-
-
-
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- namespace this_thread
- {
- void interruption_point()
- {
-#ifndef BOOST_NO_EXCEPTIONS
- 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();
- }
- }
-#endif
- }
-
- bool interruption_enabled() BOOST_NOEXCEPT
- {
- boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
- return thread_info && thread_info->interrupt_enabled;
- }
-
- bool interruption_requested() BOOST_NOEXCEPT
- {
- 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() BOOST_NOEXCEPT:
- interruption_was_enabled(interruption_enabled())
- {
- if(interruption_was_enabled)
- {
- detail::get_current_thread_data()->interrupt_enabled=false;
- }
- }
-
- disable_interruption::~disable_interruption() BOOST_NOEXCEPT
- {
- if(detail::get_current_thread_data())
- {
- detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled;
- }
- }
-
- restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
- {
- if(d.interruption_was_enabled)
- {
- detail::get_current_thread_data()->interrupt_enabled=true;
- }
- }
-
- restore_interruption::~restore_interruption() BOOST_NOEXCEPT
- {
- if(detail::get_current_thread_data())
- {
- detail::get_current_thread_data()->interrupt_enabled=false;
- }
- }
- }
-#endif
-
- 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)
- {
- 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 0;
- }
-
- void* get_tss_data(void const* key)
- {
- if(tss_data_node* const current_node=find_tss_data(key))
- {
- return current_node->value;
- }
- return 0;
- }
-
- void add_new_tss_node(void const* key,
- detail::tss_data_node::cleanup_caller_t caller,
- detail::tss_data_node::cleanup_func_t 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(caller,func,tss_data)));
- }
-
- void erase_tss_node(void const* key)
- {
- detail::thread_data_base* const current_thread_data(get_current_thread_data());
- if(current_thread_data)
- {
- current_thread_data->tss_data.erase(key);
- }
- }
-
- void set_tss_data(void const* key,
- detail::tss_data_node::cleanup_caller_t caller,
- detail::tss_data_node::cleanup_func_t 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!=0))
- {
- (*current_node->caller)(current_node->func,current_node->value);
- }
- if(func || (tss_data!=0))
- {
- current_node->caller=caller;
- current_node->func=func;
- current_node->value=tss_data;
- }
- else
- {
- erase_tss_node(key);
- }
- }
- else if(func || (tss_data!=0))
- {
- add_new_tss_node(key,caller,func,tss_data);
- }
- }
- }
-
- BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
- {
- detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
- if(current_thread_data)
- {
- current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
- }
- }
-
-//#ifndef BOOST_NO_EXCEPTIONS
-namespace detail {
-
- void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
- {
- detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
- if(current_thread_data)
- {
- current_thread_data->make_ready_at_thread_exit(as);
- }
- }
-}
-//#endif
-
-
-}
+++ /dev/null
-// (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_THREAD_WIN32) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
-
-namespace boost
-{
- /*
- 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.
- */
-
- 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_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_LIB) && !defined(_MSC_VER)
+++ /dev/null
-// 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
-// (C) Copyright 2011-2018 Vicente J. Botet Escriba
-
-//#define BOOST_THREAD_VERSION 3
-
-#include <boost/winapi/config.hpp>
-#include <boost/thread/thread_only.hpp>
-#include <boost/thread/once.hpp>
-#include <boost/thread/tss.hpp>
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/detail/tss_hooks.hpp>
-#include <boost/thread/future.hpp>
-#include <boost/assert.hpp>
-#include <boost/cstdint.hpp>
-#if defined BOOST_THREAD_USES_DATETIME
-#include <boost/date_time/posix_time/conversion.hpp>
-#include <boost/thread/thread_time.hpp>
-#endif
-#include <boost/thread/csbl/memory/unique_ptr.hpp>
-#include <memory>
-#include <algorithm>
-#ifndef UNDER_CE
-#include <process.h>
-#endif
-#include <stdio.h>
-#include <windows.h>
-#include <boost/predef/platform.h>
-
-#if BOOST_PLAT_WINDOWS_RUNTIME
-#include <mutex>
-#include <atomic>
-#include <Activation.h>
-#include <wrl\client.h>
-#include <wrl\event.h>
-#include <wrl\wrappers\corewrappers.h>
-#include <wrl\ftm.h>
-#include <windows.system.threading.h>
-#pragma comment(lib, "runtimeobject.lib")
-#endif
-
-namespace boost
-{
- namespace detail
- {
- thread_data_base::~thread_data_base()
- {
- for (notify_list_t::iterator i = notify.begin(), e = notify.end();
- i != e; ++i)
- {
- i->second->unlock();
- i->first->notify_all();
- }
-//#ifndef BOOST_NO_EXCEPTIONS
- for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
- i != e; ++i)
- {
- (*i)->notify_deferred();
- }
-//#endif
- }
- }
-
- namespace
- {
-#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
- boost::once_flag current_thread_tls_init_flag;
-#else
- boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
-#endif
-#if defined(UNDER_CE)
- // Windows CE does not define the TLS_OUT_OF_INDEXES constant.
-#define TLS_OUT_OF_INDEXES 0xFFFFFFFF
-#endif
-#if !BOOST_PLAT_WINDOWS_RUNTIME
- DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES;
-#else
- __declspec(thread) boost::detail::thread_data_base* current_thread_data_base;
-#endif
-
- void create_current_thread_tls_key()
- {
- tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in
-#if !BOOST_PLAT_WINDOWS_RUNTIME
- current_thread_tls_key=TlsAlloc();
- BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
-#endif
- }
-
- void cleanup_tls_key()
- {
-#if !BOOST_PLAT_WINDOWS_RUNTIME
- if(current_thread_tls_key!=TLS_OUT_OF_INDEXES)
- {
- TlsFree(current_thread_tls_key);
- current_thread_tls_key=TLS_OUT_OF_INDEXES;
- }
-#endif
- }
-
- void set_current_thread_data(detail::thread_data_base* new_data)
- {
- boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
-#if BOOST_PLAT_WINDOWS_RUNTIME
- current_thread_data_base = new_data;
-#else
- if (current_thread_tls_key != TLS_OUT_OF_INDEXES)
- {
- BOOST_VERIFY(TlsSetValue(current_thread_tls_key, new_data));
- }
- else
- {
- BOOST_VERIFY(false);
- //boost::throw_exception(thread_resource_error());
- }
-#endif
- }
- }
-
- namespace detail
- {
- thread_data_base* get_current_thread_data()
- {
-#if BOOST_PLAT_WINDOWS_RUNTIME
- return current_thread_data_base;
-#else
- if (current_thread_tls_key == TLS_OUT_OF_INDEXES)
- {
- return 0;
- }
- return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
-#endif
- }
- }
-
- namespace
- {
-#ifndef BOOST_HAS_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)
- {
- boost::csbl::unique_ptr<ThreadProxyData> data(reinterpret_cast<ThreadProxyData*>(args));
- DWORD ret=data->start_address_(data->arglist_);
- return ret;
- }
-
- inline uintptr_t _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
- void* arglist, unsigned initflag, unsigned* thrdaddr)
- {
- DWORD threadID;
- ThreadProxyData* data = new ThreadProxyData(start_address,arglist);
- HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
- data,initflag,&threadID);
- if (hthread==0) {
- delete data;
- return 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_)
- {}
- };
-
- }
-
-#if BOOST_PLAT_WINDOWS_RUNTIME
- namespace detail
- {
- std::atomic_uint threadCount;
-
- bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId)
- {
- Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IThreadPoolStatics> threadPoolFactory;
- HRESULT hr = ::Windows::Foundation::GetActivationFactory(
- Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(),
- &threadPoolFactory);
- if (hr != S_OK)
- {
- return false;
- }
-
- // Create event for tracking work item completion.
- *thrdId = ++threadCount;
- handle completionHandle = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS);
- if (!completionHandle)
- {
- return false;
- }
- m_completionHandle = completionHandle;
-
- // Create new work item.
- Microsoft::WRL::ComPtr<ABI::Windows::System::Threading::IWorkItemHandler> workItem =
- Microsoft::WRL::Callback<Microsoft::WRL::Implements<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>>
- ([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *)
- {
- // Add a reference since we need to access the completionHandle after the thread_start_function.
- // This is to handle cases where detach() was called and run_thread_exit_callbacks() would end
- // up closing the handle.
- ::boost::detail::thread_data_base* const thread_info(reinterpret_cast<::boost::detail::thread_data_base*>(parameter));
- intrusive_ptr_add_ref(thread_info);
-
- __try
- {
- address(parameter);
- }
- __finally
- {
- SetEvent(completionHandle);
- intrusive_ptr_release(thread_info);
- }
- return S_OK;
- });
-
- // Schedule work item on the threadpool.
- Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> asyncAction;
- hr = threadPoolFactory->RunWithPriorityAndOptionsAsync(
- workItem.Get(),
- ABI::Windows::System::Threading::WorkItemPriority_Normal,
- ABI::Windows::System::Threading::WorkItemOptions_TimeSliced,
- &asyncAction);
- return hr == S_OK;
- }
- }
-#endif
-
- namespace
- {
- void run_thread_exit_callbacks()
- {
- detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false);
- if(current_thread_data)
- {
- while(! current_thread_data->tss_data.empty() || 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.empty())
- {
- std::map<void const*,detail::tss_data_node>::iterator current
- = current_thread_data->tss_data.begin();
- if(current->second.func && (current->second.value!=0))
- {
- (*current->second.caller)(current->second.func,current->second.value);
- }
- current_thread_data->tss_data.erase(current);
- }
- }
- 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);
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- BOOST_TRY
- {
-#endif
- thread_info->run();
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- }
- BOOST_CATCH(thread_interrupted const&)
- {
- }
- // Unhandled exceptions still cause the application to terminate
- BOOST_CATCH_END
-#endif
- run_thread_exit_callbacks();
- return 0;
- }
- }
-
- thread::thread() BOOST_NOEXCEPT
- {}
-
- bool thread::start_thread_noexcept()
- {
-#if BOOST_PLAT_WINDOWS_RUNTIME
- intrusive_ptr_add_ref(thread_info.get());
- if (!thread_info->thread_handle.start(&thread_start_function, thread_info.get(), &thread_info->id))
- {
- intrusive_ptr_release(thread_info.get());
- return false;
- }
- return true;
-#else
- uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
- if(!new_thread)
- {
- return false;
- }
- intrusive_ptr_add_ref(thread_info.get());
- thread_info->thread_handle=(detail::win32::handle)(new_thread);
- ResumeThread(thread_info->thread_handle);
- return true;
-#endif
- }
-
- bool thread::start_thread_noexcept(const attributes& attr)
- {
-#if BOOST_PLAT_WINDOWS_RUNTIME
- // Stack size isn't supported with Windows Runtime.
- attr;
- return start_thread_noexcept();
-#else
- uintptr_t const new_thread=_beginthreadex(0,static_cast<unsigned int>(attr.get_stack_size()),&thread_start_function,thread_info.get(),
- CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_info->id);
- if(!new_thread)
- {
- return false;
- }
- intrusive_ptr_add_ref(thread_info.get());
- thread_info->thread_handle=(detail::win32::handle)(new_thread);
- ResumeThread(thread_info->thread_handle);
- return true;
-#endif
- }
-
- thread::thread(detail::thread_data_ptr data):
- thread_info(data)
- {}
-
- namespace
- {
- struct externally_launched_thread:
- detail::thread_data_base
- {
- externally_launched_thread()
- {
- ++count;
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- interruption_enabled=false;
-#endif
- }
- ~externally_launched_thread() {
- BOOST_ASSERT(notify.empty());
- notify.clear();
-//#ifndef BOOST_NO_EXCEPTIONS
- BOOST_ASSERT(async_states_.empty());
- async_states_.clear();
-//#endif
- }
-
- void run()
- {}
- void notify_all_at_thread_exit(condition_variable*, mutex*)
- {}
-
- 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>();
- BOOST_TRY
- {
- set_current_thread_data(me);
- }
- BOOST_CATCH(...)
- {
- detail::heap_delete(me);
- BOOST_RETHROW
- }
- BOOST_CATCH_END
- }
-
- 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)
- {
- make_external_thread_data();
- current_thread_data=detail::get_current_thread_data();
- }
- return current_thread_data;
- }
- }
-
- thread::id thread::get_id() const BOOST_NOEXCEPT
- {
-#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
- detail::thread_data_ptr local_thread_info=(get_thread_info)();
- if(!local_thread_info)
- {
- return 0;
- }
- return local_thread_info->id;
-#else
- return thread::id((get_thread_info)());
-#endif
- }
-
- bool thread::joinable() const BOOST_NOEXCEPT
- {
- detail::thread_data_ptr local_thread_info = (get_thread_info)();
- if(!local_thread_info)
- {
- return false;
- }
- return true;
- }
- bool thread::join_noexcept()
- {
- detail::thread_data_ptr local_thread_info=(get_thread_info)();
- if(local_thread_info)
- {
- this_thread::interruptible_wait(this->native_handle(), detail::internal_platform_timepoint::getMax());
- release_handle();
- return true;
- }
- else
- {
- return false;
- }
- }
-
- bool thread::do_try_join_until_noexcept(detail::internal_platform_timepoint const &timeout, bool& res)
- {
- detail::thread_data_ptr local_thread_info=(get_thread_info)();
- if(local_thread_info)
- {
- if(!this_thread::interruptible_wait(this->native_handle(), timeout))
- {
- res=false;
- return true;
- }
- release_handle();
- res=true;
- return true;
- }
- else
- {
- return false;
- }
- }
-
- void thread::detach()
- {
- release_handle();
- }
-
- void thread::release_handle()
- {
- thread_info=0;
- }
-
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- 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 BOOST_NOEXCEPT
- {
- detail::thread_data_ptr local_thread_info=(get_thread_info)();
- return local_thread_info.get() && (winapi::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0);
- }
-
-#endif
-
- unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
- {
- detail::win32::system_info info;
- detail::win32::get_system_info(&info);
- return info.dwNumberOfProcessors;
- }
-
- unsigned thread::physical_concurrency() BOOST_NOEXCEPT
- {
- // a bit too strict: Windows XP with SP3 would be sufficient
-#if BOOST_PLAT_WINDOWS_RUNTIME \
- || ( BOOST_USE_WINAPI_VERSION <= BOOST_WINAPI_VERSION_WINXP ) \
- || ( ( defined(__MINGW32__) && !defined(__MINGW64__) ) && _WIN32_WINNT < 0x0600)
- return 0;
-#else
- unsigned cores = 0;
- DWORD size = 0;
-
- GetLogicalProcessorInformation(NULL, &size);
- if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
- return 0;
- const size_t Elements = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
-
- std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(Elements);
- if (GetLogicalProcessorInformation(&buffer.front(), &size) == FALSE)
- return 0;
-
-
- for (size_t i = 0; i < Elements; ++i) {
- if (buffer[i].Relationship == RelationProcessorCore)
- ++cores;
- }
- return cores;
-#endif
- }
-
- thread::native_handle_type thread::native_handle()
- {
- detail::thread_data_ptr local_thread_info=(get_thread_info)();
- if(!local_thread_info)
- {
- return detail::win32::invalid_handle_value;
- }
-#if BOOST_PLAT_WINDOWS_RUNTIME
- // There is no 'real' Win32 handle so we return a handle that at least can be waited on.
- return local_thread_info->thread_handle.waitable_handle();
-#else
- return (detail::win32::handle)local_thread_info->thread_handle;
-#endif
- }
-
- detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
- {
- return thread_info;
- }
-
- namespace this_thread
- {
-#ifndef UNDER_CE
-#if !BOOST_PLAT_WINDOWS_RUNTIME
- namespace detail_
- {
- typedef struct _REASON_CONTEXT {
- ULONG Version;
- DWORD Flags;
- union {
- LPWSTR SimpleReasonString;
- struct {
- HMODULE LocalizedReasonModule;
- ULONG LocalizedReasonId;
- ULONG ReasonStringCount;
- LPWSTR *ReasonStrings;
- } Detailed;
- } Reason;
- } REASON_CONTEXT, *PREASON_CONTEXT;
- typedef BOOL (WINAPI *setwaitabletimerex_t)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, PREASON_CONTEXT, ULONG);
- static inline BOOL WINAPI SetWaitableTimerEx_emulation(HANDLE hTimer, const LARGE_INTEGER *lpDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext, ULONG TolerableDelay)
- {
- return SetWaitableTimer(hTimer, lpDueTime, lPeriod, pfnCompletionRoutine, lpArgToCompletionRoutine, FALSE);
- }
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable: 6387) // MSVC sanitiser warns that GetModuleHandleA() might fail
-#endif
- static inline setwaitabletimerex_t SetWaitableTimerEx()
- {
- static setwaitabletimerex_t setwaitabletimerex_impl;
- if(setwaitabletimerex_impl)
- return setwaitabletimerex_impl;
- void (*addr)()=(void (*)()) GetProcAddress(
-#if !defined(BOOST_NO_ANSI_APIS)
- GetModuleHandleA("KERNEL32.DLL"),
-#else
- GetModuleHandleW(L"KERNEL32.DLL"),
-#endif
- "SetWaitableTimerEx");
- if(addr)
- setwaitabletimerex_impl=(setwaitabletimerex_t) addr;
- else
- setwaitabletimerex_impl=&SetWaitableTimerEx_emulation;
- return setwaitabletimerex_impl;
- }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
- }
-#endif
-#endif
- bool interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout)
- {
- detail::win32::handle handles[4]={0};
- unsigned handle_count=0;
- unsigned wait_handle_index=~0U;
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- unsigned interruption_index=~0U;
-#endif
- 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 defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled)
- {
- interruption_index=handle_count;
- handles[handle_count++]=detail::get_current_thread_data()->interruption_handle;
- }
-#endif
- detail::win32::handle_manager timer_handle;
-
-#ifndef UNDER_CE
-#if !BOOST_PLAT_WINDOWS_RUNTIME
- // Preferentially use coalescing timers for better power consumption and timer accuracy
- if(timeout != detail::internal_platform_timepoint::getMax())
- {
- boost::intmax_t const time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
- timer_handle=CreateWaitableTimer(NULL,false,NULL);
- if(timer_handle!=0)
- {
- ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
- if(time_left_msec/20>tolerable) // 5%
- tolerable=static_cast<ULONG>(time_left_msec/20);
- LARGE_INTEGER due_time={{0,0}};
- if(time_left_msec>0)
- {
- due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time
- }
- bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0;
- if(set_time_succeeded)
- {
- timeout_index=handle_count;
- handles[handle_count++]=timer_handle;
- }
- }
- }
-#endif
-#endif
-
- bool const using_timer=timeout_index!=~0u;
- boost::intmax_t time_left_msec(INFINITE);
- if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
- {
- time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
- if(time_left_msec < 0)
- {
- time_left_msec = 0;
- }
- }
-
- do
- {
- if(handle_count)
- {
- unsigned long const notified_index=winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast<DWORD>(time_left_msec), 0);
- if(notified_index<handle_count)
- {
- if(notified_index==wait_handle_index)
- {
- return true;
- }
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- else if(notified_index==interruption_index)
- {
- winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
- throw thread_interrupted();
- }
-#endif
- else if(notified_index==timeout_index)
- {
- return false;
- }
- }
- }
- else
- {
- detail::win32::sleep(static_cast<unsigned long>(time_left_msec));
- }
-
- if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
- {
- time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
- }
- }
- while(time_left_msec == INFINITE || time_left_msec > 0);
- return false;
- }
-
- namespace no_interruption_point
- {
- bool non_interruptible_wait(detail::win32::handle handle_to_wait_for, detail::internal_platform_timepoint const &timeout)
- {
- detail::win32::handle handles[3]={0};
- unsigned handle_count=0;
- unsigned wait_handle_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;
- }
- detail::win32::handle_manager timer_handle;
-
-#ifndef UNDER_CE
-#if !BOOST_PLAT_WINDOWS_RUNTIME
- // Preferentially use coalescing timers for better power consumption and timer accuracy
- if(timeout != detail::internal_platform_timepoint::getMax())
- {
- boost::intmax_t const time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
- timer_handle=CreateWaitableTimer(NULL,false,NULL);
- if(timer_handle!=0)
- {
- ULONG tolerable=32; // Empirical testing shows Windows ignores this when <= 26
- if(time_left_msec/20>tolerable) // 5%
- tolerable=static_cast<ULONG>(time_left_msec/20);
- LARGE_INTEGER due_time={{0,0}};
- if(time_left_msec>0)
- {
- due_time.QuadPart=-(time_left_msec*10000); // negative indicates relative time
- }
- bool const set_time_succeeded=detail_::SetWaitableTimerEx()(timer_handle,&due_time,0,0,0,NULL,tolerable)!=0;
- if(set_time_succeeded)
- {
- timeout_index=handle_count;
- handles[handle_count++]=timer_handle;
- }
- }
- }
-#endif
-#endif
-
- bool const using_timer=timeout_index!=~0u;
- boost::intmax_t time_left_msec(INFINITE);
- if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
- {
- time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
- if(time_left_msec < 0)
- {
- time_left_msec = 0;
- }
- }
-
- do
- {
- if(handle_count)
- {
- unsigned long const notified_index=winapi::WaitForMultipleObjectsEx(handle_count,handles,false,static_cast<DWORD>(time_left_msec), 0);
- if(notified_index<handle_count)
- {
- if(notified_index==wait_handle_index)
- {
- return true;
- }
- else if(notified_index==timeout_index)
- {
- return false;
- }
- }
- }
- else
- {
- detail::win32::sleep(static_cast<unsigned long>(time_left_msec));
- }
-
- if(!using_timer && timeout != detail::internal_platform_timepoint::getMax())
- {
- time_left_msec = (timeout - detail::internal_platform_clock::now()).getMs();
- }
- }
- while(time_left_msec == INFINITE || time_left_msec > 0);
- return false;
- }
- }
-
- thread::id get_id() BOOST_NOEXCEPT
- {
-#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
-#if BOOST_PLAT_WINDOWS_RUNTIME
- detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
- if (current_thread_data)
- {
- return current_thread_data->id;
- }
-#endif
- return winapi::GetCurrentThreadId();
-#else
- return thread::id(get_or_make_current_thread_data());
-#endif
- }
-
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- void interruption_point()
- {
- if(interruption_enabled() && interruption_requested())
- {
- winapi::ResetEvent(detail::get_current_thread_data()->interruption_handle);
- throw thread_interrupted();
- }
- }
-
- bool interruption_enabled() BOOST_NOEXCEPT
- {
- return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled;
- }
-
- bool interruption_requested() BOOST_NOEXCEPT
- {
- return detail::get_current_thread_data() && (winapi::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0);
- }
-#endif
-
- void yield() BOOST_NOEXCEPT
- {
- detail::win32::sleep(0);
- }
-
-#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
- disable_interruption::disable_interruption() BOOST_NOEXCEPT:
- interruption_was_enabled(interruption_enabled())
- {
- if(interruption_was_enabled)
- {
- detail::get_current_thread_data()->interruption_enabled=false;
- }
- }
-
- disable_interruption::~disable_interruption() BOOST_NOEXCEPT
- {
- if(detail::get_current_thread_data())
- {
- detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled;
- }
- }
-
- restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
- {
- if(d.interruption_was_enabled)
- {
- detail::get_current_thread_data()->interruption_enabled=true;
- }
- }
-
- restore_interruption::~restore_interruption() BOOST_NOEXCEPT
- {
- if(detail::get_current_thread_data())
- {
- detail::get_current_thread_data()->interruption_enabled=false;
- }
- }
-#endif
- }
-
- 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)
- {
- 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,
- detail::tss_data_node::cleanup_caller_t caller,
- detail::tss_data_node::cleanup_func_t 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(caller,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,
- detail::tss_data_node::cleanup_caller_t caller,
- detail::tss_data_node::cleanup_func_t 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!=0))
- {
- (*current_node->caller)(current_node->func,current_node->value);
- }
- if(func || (tss_data!=0))
- {
- current_node->caller=caller;
- current_node->func=func;
- current_node->value=tss_data;
- }
- else
- {
- erase_tss_node(key);
- }
- }
- else if(func || (tss_data!=0))
- {
- add_new_tss_node(key,caller,func,tss_data);
- }
- }
- }
-
- BOOST_THREAD_DECL void __cdecl on_process_enter()
- {}
-
- BOOST_THREAD_DECL void __cdecl on_thread_enter()
- {}
-
- BOOST_THREAD_DECL void __cdecl on_process_exit()
- {
- boost::cleanup_tls_key();
- }
-
- BOOST_THREAD_DECL void __cdecl on_thread_exit()
- {
- boost::run_thread_exit_callbacks();
- }
-
- BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
- {
- detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
- if(current_thread_data)
- {
- current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
- }
- }
-}
-
+++ /dev/null
-// (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/winapi/config.hpp>
-#include <boost/thread/detail/config.hpp>
-
-
-#if defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_DLL)
-
- #include <boost/thread/detail/tss_hooks.hpp>
-
- #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:
- {
- 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
-{
- 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.
- */
- }
-}
-
-#else //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_DLL)
-
-#ifdef _MSC_VER
-// Prevent LNK4221 warning with link=static
-namespace boost { namespace link_static_warning_inhibit {
- extern __declspec(dllexport) void foo() { }
-} }
-#endif
-
-#endif //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_DLL)
+++ /dev/null
-// $Id$
-// (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/winapi/config.hpp>
-#include <boost/thread/detail/config.hpp>
-
-#if defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_LIB)
-
-#if (defined(__MINGW32__) && !defined(_WIN64)) || defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR)
-
-#include <boost/thread/detail/tss_hooks.hpp>
-
-#include <windows.h>
-
-#include <cstdlib>
-
-namespace boost
-{
- void tss_cleanup_implemented() {}
-}
-
-namespace {
- void NTAPI on_tls_callback(void* , DWORD dwReason, PVOID )
- {
- switch (dwReason)
- {
- case DLL_THREAD_DETACH:
- {
- boost::on_thread_exit();
- break;
- }
- }
- }
-}
-
-#if defined(__MINGW64__) || (__MINGW64_VERSION_MAJOR) || (__MINGW32__) || (__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 <boost/thread/detail/tss_hooks.hpp>
-
- #include <stdlib.h>
-
- #include <windows.h>
-
-
-// _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)(HINSTANCE, DWORD, LPVOID);
-extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HINSTANCE, 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) || ((_MSC_VER > 1900) && (_MSC_VER < 1910)) // 1300 == VC++ 7.0, 1900 == VC++ 14.0, 1910 == VC++ 2017
- typedef void ( __cdecl *_PVFV_ )();
- typedef void ( __cdecl *_PIFV_ )();
- #define INIRETSUCCESS_V
- #define INIRETSUCCESS_I
- #define PVAPI_V void __cdecl
- #define PVAPI_I void __cdecl
- #elif (_MSC_VER >= 1910)
- typedef void ( __cdecl *_PVFV_ )();
- typedef int ( __cdecl *_PIFV_ )();
- #define INIRETSUCCESS_V
- #define INIRETSUCCESS_I 0
- #define PVAPI_V void __cdecl
- #define PVAPI_I int __cdecl
- #else
- typedef int ( __cdecl *_PVFV_ )();
- typedef int ( __cdecl *_PIFV_ )();
- #define INIRETSUCCESS_V 0
- #define INIRETSUCCESS_I 0
- #define PVAPI_V int __cdecl
- #define PVAPI_I 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_I on_tls_prepare();
- static PVAPI_V on_process_init();
- static PVAPI_V 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"))_PIFV_ 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 _PIFV_ 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_I 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_I;
- }
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
- PVAPI_V 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_V;
- }
-
- PVAPI_V on_process_term()
- {
- boost::on_process_exit();
- return INIRETSUCCESS_V;
- }
-
- 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(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
-#else
- BOOL WINAPI dll_callback(HINSTANCE, 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)(HINSTANCE, DWORD, LPVOID)=&dll_callback;
-}
-namespace boost
-{
- 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.
- */
- }
-}
-
-#endif //defined(_MSC_VER) && !defined(UNDER_CE)
-
-#endif //defined(BOOST_THREAD_WIN32) && defined(BOOST_THREAD_BUILD_LIB)