BVB Source Codes

mars Show thread.cpp Source code

Return Download mars: download thread.cpp Source code - Download mars Source code - Type:.cpp
  1. // Copyright (C) 2001-2003
  2. // William E. Kempf
  3. // Copyright (C) 2007-8 Anthony Williams
  4. // (C) Copyright 2011-2012 Vicente J. Botet Escriba
  5. //
  6. //  Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8.  
  9. #include <boost/thread/detail/config.hpp>
  10.  
  11. #include <boost/thread/thread_only.hpp>
  12. #if defined BOOST_THREAD_USES_DATETIME
  13. #include <boost/thread/xtime.hpp>
  14. #endif
  15. #include <boost/thread/condition_variable.hpp>
  16. #include <boost/thread/locks.hpp>
  17. #include <boost/thread/once.hpp>
  18. #include <boost/thread/tss.hpp>
  19. #include <boost/thread/future.hpp>
  20.  
  21. #ifdef __GLIBC__
  22. #include <sys/sysinfo.h>
  23. #elif defined(__APPLE__) || defined(__FreeBSD__)
  24. #include <sys/types.h>
  25. #include <sys/sysctl.h>
  26. #elif defined BOOST_HAS_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29.  
  30. #include <boost/algorithm/string/split.hpp>
  31. #include <boost/algorithm/string/trim.hpp>
  32. #include <boost/lexical_cast.hpp>
  33.  
  34. #include <fstream>
  35. #include <string>
  36. #include <set>
  37. #include <vector>
  38. #include <string.h> // memcmp.
  39.  
  40. namespace mars_boost {} namespace boost = mars_boost; namespace mars_boost
  41. {
  42.     namespace detail
  43.     {
  44.         thread_data_base::~thread_data_base()
  45.         {
  46.             for (notify_list_t::iterator i = notify.begin(), e = notify.end();
  47.                     i != e; ++i)
  48.             {
  49.                 i->second->unlock();
  50.                 i->first->notify_all();
  51.             }
  52.             for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
  53.                     i != e; ++i)
  54.             {
  55.                 (*i)->make_ready();
  56.             }
  57.         }
  58.  
  59.         struct thread_exit_callback_node
  60.         {
  61.             mars_boost::detail::thread_exit_function_base* func;
  62.             thread_exit_callback_node* next;
  63.  
  64.             thread_exit_callback_node(mars_boost::detail::thread_exit_function_base* func_,
  65.                                       thread_exit_callback_node* next_):
  66.                 func(func_),next(next_)
  67.             {}
  68.         };
  69.  
  70.         namespace
  71.         {
  72. #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11
  73.           mars_boost::once_flag current_thread_tls_init_flag;
  74. #else
  75.             mars_boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
  76. #endif
  77.             pthread_key_t current_thread_tls_key;
  78.  
  79.             extern "C"
  80.             {
  81.                 static void tls_destructor(void* data)
  82.                 {
  83.                     //mars_boost::detail::thread_data_base* thread_info=static_cast<mars_boost::detail::thread_data_base*>(data);
  84.                     mars_boost::detail::thread_data_ptr thread_info = static_cast<mars_boost::detail::thread_data_base*>(data)->shared_from_this();
  85.  
  86.                     if(thread_info)
  87.                     {
  88.                         while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
  89.                         {
  90.  
  91.                             while(thread_info->thread_exit_callbacks)
  92.                             {
  93.                                 detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks;
  94.                                 thread_info->thread_exit_callbacks=current_node->next;
  95.                                 if(current_node->func)
  96.                                 {
  97.                                     (*current_node->func)();
  98.                                     delete current_node->func;
  99.                                 }
  100.                                 delete current_node;
  101.                             }
  102.                             while (!thread_info->tss_data.empty())
  103.                             {
  104.                                 std::map<void const*,detail::tss_data_node>::iterator current
  105.                                     = thread_info->tss_data.begin();
  106.                                 if(current->second.func && (current->second.value!=0))
  107.                                 {
  108.                                     (*current->second.func)(current->second.value);
  109.                                 }
  110.                                 thread_info->tss_data.erase(current);
  111.                             }
  112.                         }
  113.                         thread_info->self.reset();
  114.                     }
  115.                 }
  116.             }
  117.  
  118. #if defined BOOST_THREAD_PATCH
  119.             struct  delete_current_thread_tls_key_on_dlclose_t
  120.             {
  121.                 delete_current_thread_tls_key_on_dlclose_t()
  122.                 {
  123.                 }
  124.                 ~delete_current_thread_tls_key_on_dlclose_t()
  125.                 {
  126.                     const mars_boost::once_flag uninitialized = BOOST_ONCE_INIT;
  127.                     if (memcmp(&current_thread_tls_init_flag, &uninitialized, sizeof(mars_boost::once_flag)))
  128.                     {
  129.                       void* data = pthread_getspecific(current_thread_tls_key);
  130.                       if (data)
  131.                           tls_destructor(data);
  132.                         pthread_key_delete(current_thread_tls_key);
  133.                     }
  134.                 }
  135.             };
  136.             delete_current_thread_tls_key_on_dlclose_t delete_current_thread_tls_key_on_dlclose;
  137. #endif
  138.             void create_current_thread_tls_key()
  139.             {
  140.                 BOOST_VERIFY(!pthread_key_create(&current_thread_tls_key,&tls_destructor));
  141.             }
  142.         }
  143.  
  144.         mars_boost::detail::thread_data_base* get_current_thread_data()
  145.         {
  146.             mars_boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
  147.             return (mars_boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);
  148.         }
  149.  
  150.         void set_current_thread_data(detail::thread_data_base* new_data)
  151.         {
  152.             mars_boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
  153.             BOOST_VERIFY(!pthread_setspecific(current_thread_tls_key,new_data));
  154.         }
  155.     }
  156.  
  157.     namespace
  158.     {
  159.         extern "C"
  160.         {
  161.             static void* thread_proxy(void* param)
  162.             {
  163.                 //mars_boost::detail::thread_data_ptr thread_info = static_cast<mars_boost::detail::thread_data_base*>(param)->self;
  164.                 mars_boost::detail::thread_data_ptr thread_info = static_cast<mars_boost::detail::thread_data_base*>(param)->shared_from_this();
  165.                 thread_info->self.reset();
  166.                 detail::set_current_thread_data(thread_info.get());
  167. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  168.                 BOOST_TRY
  169.                 {
  170. #endif
  171.                     thread_info->run();
  172. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  173.  
  174.                 }
  175.                 BOOST_CATCH (thread_interrupted const&)
  176.                 {
  177.                 }
  178. // Removed as it stops the debugger identifying the cause of the exception
  179. // Unhandled exceptions still cause the application to terminate
  180. //                 BOOST_CATCH(...)
  181. //                 {
  182. //                   throw;
  183. //
  184. //                     std::terminate();
  185. //                 }
  186.                 BOOST_CATCH_END
  187. #endif
  188.                 detail::tls_destructor(thread_info.get());
  189.                 detail::set_current_thread_data(0);
  190.                 mars_boost::lock_guard<mars_boost::mutex> lock(thread_info->data_mutex);
  191.                 thread_info->done=true;
  192.                 thread_info->done_condition.notify_all();
  193.  
  194.                 return 0;
  195.             }
  196.         }
  197.     }
  198.     namespace detail
  199.     {
  200.         struct externally_launched_thread:
  201.             detail::thread_data_base
  202.         {
  203.             externally_launched_thread()
  204.             {
  205. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  206.                 interrupt_enabled=false;
  207. #endif
  208.             }
  209.             ~externally_launched_thread() {
  210.               BOOST_ASSERT(notify.empty());
  211.               notify.clear();
  212.               BOOST_ASSERT(async_states_.empty());
  213.               async_states_.clear();
  214.             }
  215.             void run()
  216.             {}
  217.             void notify_all_at_thread_exit(condition_variable*, mutex*)
  218.             {}
  219.  
  220.         private:
  221.             externally_launched_thread(externally_launched_thread&);
  222.             void operator=(externally_launched_thread&);
  223.         };
  224.  
  225.         thread_data_base* make_external_thread_data()
  226.         {
  227.             thread_data_base* const me(detail::heap_new<externally_launched_thread>());
  228.             me->self.reset(me);
  229.             set_current_thread_data(me);
  230.             return me;
  231.         }
  232.  
  233.  
  234.         thread_data_base* get_or_make_current_thread_data()
  235.         {
  236.             thread_data_base* current_thread_data(get_current_thread_data());
  237.             if(!current_thread_data)
  238.             {
  239.                 current_thread_data=make_external_thread_data();
  240.             }
  241.             return current_thread_data;
  242.         }
  243.  
  244.     }
  245.  
  246.  
  247.     thread::thread() BOOST_NOEXCEPT
  248.     {}
  249.  
  250.     bool thread::start_thread_noexcept()
  251.     {
  252.         thread_info->self=thread_info;
  253.         int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get());
  254.         if (res != 0)
  255.         {
  256.             thread_info->self.reset();
  257.             return false;
  258.         }
  259.         return true;
  260.     }
  261.  
  262.     bool thread::start_thread_noexcept(const attributes& attr)
  263.     {
  264.         thread_info->self=thread_info;
  265.         const attributes::native_handle_type* h = attr.native_handle();
  266.         int res = pthread_create(&thread_info->thread_handle, h, &thread_proxy, thread_info.get());
  267.         if (res != 0)
  268.         {
  269.             thread_info->self.reset();
  270.             return false;
  271.         }
  272.         int detached_state;
  273.         res = pthread_attr_getdetachstate(h, &detached_state);
  274.         if (res != 0)
  275.         {
  276.             thread_info->self.reset();
  277.             return false;
  278.         }
  279.         if (PTHREAD_CREATE_DETACHED==detached_state)
  280.         {
  281.           detail::thread_data_ptr local_thread_info;
  282.           thread_info.swap(local_thread_info);
  283.  
  284.           if(local_thread_info)
  285.           {
  286.               //lock_guard<mutex> lock(local_thread_info->data_mutex);
  287.               if(!local_thread_info->join_started)
  288.               {
  289.                   //BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle));
  290.                   local_thread_info->join_started=true;
  291.                   local_thread_info->joined=true;
  292.               }
  293.           }
  294.         }
  295.         return true;
  296.     }
  297.  
  298.  
  299.  
  300.     detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const
  301.     {
  302.         return thread_info;
  303.     }
  304.  
  305.     bool thread::join_noexcept()
  306.     {
  307.         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
  308.         if(local_thread_info)
  309.         {
  310.             bool do_join=false;
  311.  
  312.             {
  313.                 unique_lock<mutex> lock(local_thread_info->data_mutex);
  314.                 while(!local_thread_info->done)
  315.                 {
  316.                     local_thread_info->done_condition.wait(lock);
  317.                 }
  318.                 do_join=!local_thread_info->join_started;
  319.  
  320.                 if(do_join)
  321.                 {
  322.                     local_thread_info->join_started=true;
  323.                 }
  324.                 else
  325.                 {
  326.                     while(!local_thread_info->joined)
  327.                     {
  328.                         local_thread_info->done_condition.wait(lock);
  329.                     }
  330.                 }
  331.             }
  332.             if(do_join)
  333.             {
  334.                 void* result=0;
  335.                 BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result));
  336.                 lock_guard<mutex> lock(local_thread_info->data_mutex);
  337.                 local_thread_info->joined=true;
  338.                 local_thread_info->done_condition.notify_all();
  339.             }
  340.  
  341.             if(thread_info==local_thread_info)
  342.             {
  343.                 thread_info.reset();
  344.             }
  345.             return true;
  346.         }
  347.         else
  348.         {
  349.           return false;
  350.         }
  351.     }
  352.  
  353.     bool thread::do_try_join_until_noexcept(struct timespec const &timeout, bool& res)
  354.     {
  355.         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
  356.         if(local_thread_info)
  357.         {
  358.             bool do_join=false;
  359.  
  360.             {
  361.                 unique_lock<mutex> lock(local_thread_info->data_mutex);
  362.                 while(!local_thread_info->done)
  363.                 {
  364.                     if(!local_thread_info->done_condition.do_wait_until(lock,timeout))
  365.                     {
  366.                       res=false;
  367.                       return true;
  368.                     }
  369.                 }
  370.                 do_join=!local_thread_info->join_started;
  371.  
  372.                 if(do_join)
  373.                 {
  374.                     local_thread_info->join_started=true;
  375.                 }
  376.                 else
  377.                 {
  378.                     while(!local_thread_info->joined)
  379.                     {
  380.                         local_thread_info->done_condition.wait(lock);
  381.                     }
  382.                 }
  383.             }
  384.             if(do_join)
  385.             {
  386.                 void* result=0;
  387.                 BOOST_VERIFY(!pthread_join(local_thread_info->thread_handle,&result));
  388.                 lock_guard<mutex> lock(local_thread_info->data_mutex);
  389.                 local_thread_info->joined=true;
  390.                 local_thread_info->done_condition.notify_all();
  391.             }
  392.  
  393.             if(thread_info==local_thread_info)
  394.             {
  395.                 thread_info.reset();
  396.             }
  397.             res=true;
  398.             return true;
  399.         }
  400.         else
  401.         {
  402.           return false;
  403.         }
  404.     }
  405.  
  406.     bool thread::joinable() const BOOST_NOEXCEPT
  407.     {
  408.         return (get_thread_info)()?true:false;
  409.     }
  410.  
  411.  
  412.     void thread::detach()
  413.     {
  414.         detail::thread_data_ptr local_thread_info;
  415.         thread_info.swap(local_thread_info);
  416.  
  417.         if(local_thread_info)
  418.         {
  419.             lock_guard<mutex> lock(local_thread_info->data_mutex);
  420.             if(!local_thread_info->join_started)
  421.             {
  422.                 BOOST_VERIFY(!pthread_detach(local_thread_info->thread_handle));
  423.                 local_thread_info->join_started=true;
  424.                 local_thread_info->joined=true;
  425.             }
  426.         }
  427.     }
  428.  
  429.     namespace this_thread
  430.     {
  431.       namespace no_interruption_point
  432.       {
  433.         namespace hiden
  434.         {
  435.           void BOOST_THREAD_DECL sleep_for(const timespec& ts)
  436.           {
  437.  
  438.                 if (mars_boost::detail::timespec_ge(ts, mars_boost::detail::timespec_zero()))
  439.                 {
  440.  
  441.     #   if defined(BOOST_HAS_PTHREAD_DELAY_NP)
  442.     #     if defined(__IBMCPP__) ||  defined(_AIX)
  443.                   BOOST_VERIFY(!pthread_delay_np(const_cast<timespec*>(&ts)));
  444.     #     else
  445.                   BOOST_VERIFY(!pthread_delay_np(&ts));
  446.     #     endif
  447.     #   elif defined(BOOST_HAS_NANOSLEEP)
  448.                   //  nanosleep takes a timespec that is an offset, not
  449.                   //  an absolute time.
  450.                   nanosleep(&ts, 0);
  451.     #   else
  452.                   mutex mx;
  453.                   unique_lock<mutex> lock(mx);
  454.                   condition_variable cond;
  455.                   cond.do_wait_for(lock, ts);
  456.     #   endif
  457.                 }
  458.           }
  459.  
  460.           void BOOST_THREAD_DECL sleep_until(const timespec& ts)
  461.           {
  462.                 timespec now = mars_boost::detail::timespec_now();
  463.                 if (mars_boost::detail::timespec_gt(ts, now))
  464.                 {
  465.                   for (int foo=0; foo < 5; ++foo)
  466.                   {
  467.  
  468.     #   if defined(BOOST_HAS_PTHREAD_DELAY_NP)
  469.                     timespec d = mars_boost::detail::timespec_minus(ts, now);
  470.                     BOOST_VERIFY(!pthread_delay_np(&d));
  471.     #   elif defined(BOOST_HAS_NANOSLEEP)
  472.                     //  nanosleep takes a timespec that is an offset, not
  473.                     //  an absolute time.
  474.                     timespec d = mars_boost::detail::timespec_minus(ts, now);
  475.                     nanosleep(&d, 0);
  476.     #   else
  477.                     mutex mx;
  478.                     unique_lock<mutex> lock(mx);
  479.                     condition_variable cond;
  480.                     cond.do_wait_until(lock, ts);
  481.     #   endif
  482.                     timespec now2 = mars_boost::detail::timespec_now();
  483.                     if (mars_boost::detail::timespec_ge(now2, ts))
  484.                     {
  485.                       return;
  486.                     }
  487.                   }
  488.                 }
  489.           }
  490.  
  491.         }
  492.       }
  493.       namespace hiden
  494.       {
  495.         void BOOST_THREAD_DECL sleep_for(const timespec& ts)
  496.         {
  497.             mars_boost::detail::thread_data_base* const thread_info=mars_boost::detail::get_current_thread_data();
  498.  
  499.             if(thread_info)
  500.             {
  501.               unique_lock<mutex> lk(thread_info->sleep_mutex);
  502.               while( thread_info->sleep_condition.do_wait_for(lk,ts)) {}
  503.             }
  504.             else
  505.             {
  506.               mars_boost::this_thread::no_interruption_point::hiden::sleep_for(ts);
  507.             }
  508.         }
  509.  
  510.         void BOOST_THREAD_DECL sleep_until(const timespec& ts)
  511.         {
  512.             mars_boost::detail::thread_data_base* const thread_info=mars_boost::detail::get_current_thread_data();
  513.  
  514.             if(thread_info)
  515.             {
  516.               unique_lock<mutex> lk(thread_info->sleep_mutex);
  517.               while(thread_info->sleep_condition.do_wait_until(lk,ts)) {}
  518.             }
  519.             else
  520.             {
  521.               mars_boost::this_thread::no_interruption_point::hiden::sleep_until(ts);
  522.             }
  523.         }
  524.       } // hiden
  525.     } // this_thread
  526.  
  527.     namespace this_thread
  528.     {
  529.         void yield() BOOST_NOEXCEPT
  530.         {
  531. #   if defined(BOOST_HAS_SCHED_YIELD)
  532.             BOOST_VERIFY(!sched_yield());
  533. #   elif defined(BOOST_HAS_PTHREAD_YIELD)
  534.             BOOST_VERIFY(!pthread_yield());
  535. //#   elif defined BOOST_THREAD_USES_DATETIME
  536. //            xtime xt;
  537. //            xtime_get(&xt, TIME_UTC_);
  538. //            sleep(xt);
  539. //            sleep_for(chrono::milliseconds(0));
  540. #   else
  541. #error
  542.             timespec ts;
  543.             ts.tv_sec= 0;
  544.             ts.tv_nsec= 0;
  545.             hiden::sleep_for(ts);
  546. #   endif
  547.         }
  548.     }
  549.     unsigned thread::hardware_concurrency() BOOST_NOEXCEPT
  550.     {
  551. #if defined(PTW32_VERSION) || defined(__hpux)
  552.         return pthread_num_processors_np();
  553. #elif defined(__APPLE__) || defined(__FreeBSD__)
  554.         int count;
  555.         size_t size=sizeof(count);
  556.         return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
  557. #elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
  558.         int const count=sysconf(_SC_NPROCESSORS_ONLN);
  559.         return (count>0)?count:0;
  560. #elif defined(__GLIBC__)
  561.         return get_nprocs();
  562. #else
  563.         return 0;
  564. #endif
  565.     }
  566.  
  567.     unsigned thread::physical_concurrency() BOOST_NOEXCEPT
  568.     {
  569. #ifdef __linux__
  570.         try {
  571.             using namespace std;
  572.  
  573.             ifstream proc_cpuinfo ("/proc/cpuinfo");
  574.  
  575.             const string physical_id("physical id"), core_id("core id");
  576.  
  577.             typedef std::pair<unsigned, unsigned> core_entry; // [physical ID, core id]
  578.  
  579.             std::set<core_entry> cores;
  580.  
  581.             core_entry current_core_entry;
  582.  
  583.             string line;
  584.             while ( getline(proc_cpuinfo, line) ) {
  585.                 if (line.empty())
  586.                     continue;
  587.  
  588.                 vector<string> key_val(2);
  589.                 mars_boost::split(key_val, line, mars_boost::is_any_of(":"));
  590.  
  591.                 if (key_val.size() != 2)
  592.                   return hardware_concurrency();
  593.  
  594.                 string key   = key_val[0];
  595.                 string value = key_val[1];
  596.                 mars_boost::trim(key);
  597.                 mars_boost::trim(value);
  598.  
  599.                 if (key == physical_id) {
  600.                     current_core_entry.first = mars_boost::lexical_cast<unsigned>(value);
  601.                     continue;
  602.                 }
  603.  
  604.                 if (key == core_id) {
  605.                     current_core_entry.second = mars_boost::lexical_cast<unsigned>(value);
  606.                     cores.insert(current_core_entry);
  607.                     continue;
  608.                 }
  609.             }
  610.             // Fall back to hardware_concurrency() in case
  611.             // /proc/cpuinfo is formatted differently than we expect.
  612.             return cores.size() != 0 ? cores.size() : hardware_concurrency();
  613.         } catch(...) {
  614.           return hardware_concurrency();
  615.         }
  616. #elif defined(__APPLE__)
  617.         int count;
  618.         size_t size=sizeof(count);
  619.         return sysctlbyname("hw.physicalcpu",&count,&size,NULL,0)?0:count;
  620. #else
  621.         return hardware_concurrency();
  622. #endif
  623.     }
  624.  
  625. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  626.     void thread::interrupt()
  627.     {
  628.         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
  629.         if(local_thread_info)
  630.         {
  631.             lock_guard<mutex> lk(local_thread_info->data_mutex);
  632.             local_thread_info->interrupt_requested=true;
  633.             if(local_thread_info->current_cond)
  634.             {
  635.                 mars_boost::pthread::pthread_mutex_scoped_lock internal_lock(local_thread_info->cond_mutex);
  636.                 BOOST_VERIFY(!pthread_cond_broadcast(local_thread_info->current_cond));
  637.             }
  638.         }
  639.     }
  640.  
  641.     bool thread::interruption_requested() const BOOST_NOEXCEPT
  642.     {
  643.         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
  644.         if(local_thread_info)
  645.         {
  646.             lock_guard<mutex> lk(local_thread_info->data_mutex);
  647.             return local_thread_info->interrupt_requested;
  648.         }
  649.         else
  650.         {
  651.             return false;
  652.         }
  653.     }
  654. #endif
  655.  
  656.     thread::native_handle_type thread::native_handle()
  657.     {
  658.         detail::thread_data_ptr const local_thread_info=(get_thread_info)();
  659.         if(local_thread_info)
  660.         {
  661.             lock_guard<mutex> lk(local_thread_info->data_mutex);
  662.             return local_thread_info->thread_handle;
  663.         }
  664.         else
  665.         {
  666.             return pthread_t();
  667.         }
  668.     }
  669.  
  670.  
  671.  
  672. #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
  673.     namespace this_thread
  674.     {
  675.         void interruption_point()
  676.         {
  677. #ifndef BOOST_NO_EXCEPTIONS
  678.             mars_boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
  679.             if(thread_info && thread_info->interrupt_enabled)
  680.             {
  681.                 lock_guard<mutex> lg(thread_info->data_mutex);
  682.                 if(thread_info->interrupt_requested)
  683.                 {
  684.                     thread_info->interrupt_requested=false;
  685.                     throw thread_interrupted();
  686.                 }
  687.             }
  688. #endif
  689.         }
  690.  
  691.         bool interruption_enabled() BOOST_NOEXCEPT
  692.         {
  693.             mars_boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
  694.             return thread_info && thread_info->interrupt_enabled;
  695.         }
  696.  
  697.         bool interruption_requested() BOOST_NOEXCEPT
  698.         {
  699.             mars_boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
  700.             if(!thread_info)
  701.             {
  702.                 return false;
  703.             }
  704.             else
  705.             {
  706.                 lock_guard<mutex> lg(thread_info->data_mutex);
  707.                 return thread_info->interrupt_requested;
  708.             }
  709.         }
  710.  
  711.         disable_interruption::disable_interruption() BOOST_NOEXCEPT:
  712.             interruption_was_enabled(interruption_enabled())
  713.         {
  714.             if(interruption_was_enabled)
  715.             {
  716.                 detail::get_current_thread_data()->interrupt_enabled=false;
  717.             }
  718.         }
  719.  
  720.         disable_interruption::~disable_interruption() BOOST_NOEXCEPT
  721.         {
  722.             if(detail::get_current_thread_data())
  723.             {
  724.                 detail::get_current_thread_data()->interrupt_enabled=interruption_was_enabled;
  725.             }
  726.         }
  727.  
  728.         restore_interruption::restore_interruption(disable_interruption& d) BOOST_NOEXCEPT
  729.         {
  730.             if(d.interruption_was_enabled)
  731.             {
  732.                 detail::get_current_thread_data()->interrupt_enabled=true;
  733.             }
  734.         }
  735.  
  736.         restore_interruption::~restore_interruption() BOOST_NOEXCEPT
  737.         {
  738.             if(detail::get_current_thread_data())
  739.             {
  740.                 detail::get_current_thread_data()->interrupt_enabled=false;
  741.             }
  742.         }
  743.     }
  744. #endif
  745.  
  746.     namespace detail
  747.     {
  748.         void add_thread_exit_function(thread_exit_function_base* func)
  749.         {
  750.             detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
  751.             thread_exit_callback_node* const new_node=
  752.                 heap_new<thread_exit_callback_node>(func,current_thread_data->thread_exit_callbacks);
  753.             current_thread_data->thread_exit_callbacks=new_node;
  754.         }
  755.  
  756.         tss_data_node* find_tss_data(void const* key)
  757.         {
  758.             detail::thread_data_base* const current_thread_data(get_current_thread_data());
  759.             if(current_thread_data)
  760.             {
  761.                 std::map<void const*,tss_data_node>::iterator current_node=
  762.                     current_thread_data->tss_data.find(key);
  763.                 if(current_node!=current_thread_data->tss_data.end())
  764.                 {
  765.                     return &current_node->second;
  766.                 }
  767.             }
  768.             return 0;
  769.         }
  770.  
  771.         void* get_tss_data(void const* key)
  772.         {
  773.             if(tss_data_node* const current_node=find_tss_data(key))
  774.             {
  775.                 return current_node->value;
  776.             }
  777.             return 0;
  778.         }
  779.  
  780.         void add_new_tss_node(void const* key,
  781.                               mars_boost::shared_ptr<tss_cleanup_function> func,
  782.                               void* tss_data)
  783.         {
  784.             detail::thread_data_base* const current_thread_data(get_or_make_current_thread_data());
  785.             current_thread_data->tss_data.insert(std::make_pair(key,tss_data_node(func,tss_data)));
  786.         }
  787.  
  788.         void erase_tss_node(void const* key)
  789.         {
  790.             detail::thread_data_base* const current_thread_data(get_current_thread_data());
  791.             if(current_thread_data)
  792.             {
  793.                 current_thread_data->tss_data.erase(key);
  794.             }
  795.         }
  796.  
  797.         void set_tss_data(void const* key,
  798.                           mars_boost::shared_ptr<tss_cleanup_function> func,
  799.                           void* tss_data,bool cleanup_existing)
  800.         {
  801.             if(tss_data_node* const current_node=find_tss_data(key))
  802.             {
  803.                 if(cleanup_existing && current_node->func && (current_node->value!=0))
  804.                 {
  805.                     (*current_node->func)(current_node->value);
  806.                 }
  807.                 if(func || (tss_data!=0))
  808.                 {
  809.                     current_node->func=func;
  810.                     current_node->value=tss_data;
  811.                 }
  812.                 else
  813.                 {
  814.                     erase_tss_node(key);
  815.                 }
  816.             }
  817.             else if(func || (tss_data!=0))
  818.             {
  819.                 add_new_tss_node(key,func,tss_data);
  820.             }
  821.         }
  822.     }
  823.  
  824.     BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
  825.     {
  826.       detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
  827.       if(current_thread_data)
  828.       {
  829.         current_thread_data->notify_all_at_thread_exit(&cond, lk.release());
  830.       }
  831.     }
  832. namespace detail {
  833.  
  834.     void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as)
  835.     {
  836.       detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
  837.       if(current_thread_data)
  838.       {
  839.         current_thread_data->make_ready_at_thread_exit(as);
  840.       }
  841.     }
  842. }
  843.  
  844.  
  845.  
  846. }
  847.  
downloadthread.cpp Source code - Download mars Source code
Related Source Codes/Software:
Hero - Elegant transition library for iOS & tvOS 2017-06-09
deep-photo-styletransfer - Code and data for paper "Deep Photo Style Transfer... 2017-06-09
mastodon - A GNU Social-compatible microblogging server ... 2017-06-09
plyr - A simple HTML5, YouTube and Vimeo player ... 2017-06-08
prepack - Prepack is a partial evaluator for JavaScript. Pre... 2017-06-08
Public-APIs - 2017-06-09
lottie-ios - An iOS library to natively render After Effects ve... 2017-06-09
Awesome-Hacking - A collection of various awesome lists for hackers,... 2017-06-09
algorithms - Minimal examples of data structures and algorithms... 2017-06-10
lectures - Oxford Deep NLP 2017 course 2017-06-10
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top