imgtools/imglib/boostlibrary/boost/thread/detail/thread.hpp
changeset 0 044383f39525
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 #ifndef BOOST_THREAD_THREAD_COMMON_HPP
       
     2 #define BOOST_THREAD_THREAD_COMMON_HPP
       
     3 // Distributed under the Boost Software License, Version 1.0. (See
       
     4 // accompanying file LICENSE_1_0.txt or copy at
       
     5 // http://www.boost.org/LICENSE_1_0.txt)
       
     6 // (C) Copyright 2007-8 Anthony Williams
       
     7  
       
     8 #include <boost/thread/exceptions.hpp>
       
     9 #include <ostream>
       
    10 #include <boost/thread/detail/move.hpp>
       
    11 #include <boost/thread/mutex.hpp>
       
    12 #include <boost/thread/xtime.hpp>
       
    13 #include <boost/thread/detail/thread_heap_alloc.hpp>
       
    14 #include <boost/utility.hpp>
       
    15 #include <boost/assert.hpp>
       
    16 #include <list>
       
    17 #include <algorithm>
       
    18 #include <boost/ref.hpp>
       
    19 #include <boost/cstdint.hpp>
       
    20 #include <boost/bind.hpp>
       
    21 #include <stdlib.h>
       
    22 #include <memory>
       
    23 #include <boost/utility/enable_if.hpp>
       
    24 #include <boost/type_traits/remove_reference.hpp>
       
    25 
       
    26 #include <boost/config/abi_prefix.hpp>
       
    27 
       
    28 #ifdef BOOST_MSVC
       
    29 #pragma warning(push)
       
    30 #pragma warning(disable:4251)
       
    31 #endif
       
    32 
       
    33 namespace boost
       
    34 {
       
    35     namespace detail
       
    36     {
       
    37         template<typename F>
       
    38         class thread_data:
       
    39             public detail::thread_data_base
       
    40         {
       
    41         public:
       
    42 #ifdef BOOST_HAS_RVALUE_REFS
       
    43             thread_data(F&& f_):
       
    44                 f(static_cast<F&&>(f_))
       
    45             {}
       
    46 #else
       
    47             thread_data(F f_):
       
    48                 f(f_)
       
    49             {}
       
    50             thread_data(detail::thread_move_t<F> f_):
       
    51                 f(f_)
       
    52             {}
       
    53 #endif            
       
    54             void run()
       
    55             {
       
    56                 f();
       
    57             }
       
    58         private:
       
    59             F f;
       
    60 
       
    61             void operator=(thread_data&);
       
    62             thread_data(thread_data&);
       
    63         };
       
    64 
       
    65         template<typename F>
       
    66         class thread_data<boost::reference_wrapper<F> >:
       
    67             public detail::thread_data_base
       
    68         {
       
    69         private:
       
    70             F& f;
       
    71 
       
    72             void operator=(thread_data&);
       
    73             thread_data(thread_data&);
       
    74         public:
       
    75             thread_data(boost::reference_wrapper<F> f_):
       
    76                 f(f_)
       
    77             {}
       
    78             
       
    79             void run()
       
    80             {
       
    81                 f();
       
    82             }
       
    83         };
       
    84 
       
    85         template<typename F>
       
    86         class thread_data<const boost::reference_wrapper<F> >:
       
    87             public detail::thread_data_base
       
    88         {
       
    89         private:
       
    90             F& f;
       
    91             void operator=(thread_data&);
       
    92             thread_data(thread_data&);
       
    93         public:
       
    94             thread_data(const boost::reference_wrapper<F> f_):
       
    95                 f(f_)
       
    96             {}
       
    97             
       
    98             void run()
       
    99             {
       
   100                 f();
       
   101             }
       
   102         };
       
   103     }
       
   104     
       
   105     class BOOST_THREAD_DECL thread
       
   106     {
       
   107     private:
       
   108         thread(thread&);
       
   109         thread& operator=(thread&);
       
   110 
       
   111         void release_handle();
       
   112         
       
   113         mutable boost::mutex thread_info_mutex;
       
   114         detail::thread_data_ptr thread_info;
       
   115 
       
   116         void start_thread();
       
   117         
       
   118         explicit thread(detail::thread_data_ptr data);
       
   119 
       
   120         detail::thread_data_ptr get_thread_info() const;
       
   121 
       
   122 #ifdef BOOST_HAS_RVALUE_REFS
       
   123         template<typename F>
       
   124         static inline detail::thread_data_ptr make_thread_info(F&& f)
       
   125         {
       
   126             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f)));
       
   127         }
       
   128         static inline detail::thread_data_ptr make_thread_info(void (*f)())
       
   129         {
       
   130             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
       
   131         }
       
   132 #else
       
   133         template<typename F>
       
   134         static inline detail::thread_data_ptr make_thread_info(F f)
       
   135         {
       
   136             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
       
   137         }
       
   138         template<typename F>
       
   139         static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
       
   140         {
       
   141             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
       
   142         }
       
   143 
       
   144         struct dummy;
       
   145 #endif
       
   146     public:
       
   147         thread();
       
   148         ~thread();
       
   149 
       
   150 #ifdef BOOST_HAS_RVALUE_REFS
       
   151         template <class F>
       
   152         thread(F&& f):
       
   153             thread_info(make_thread_info(static_cast<F&&>(f)))
       
   154         {
       
   155             start_thread();
       
   156         }
       
   157 
       
   158         thread(thread&& other)
       
   159         {
       
   160             thread_info.swap(other.thread_info);
       
   161         }
       
   162         
       
   163         thread& operator=(thread&& other)
       
   164         {
       
   165             thread_info=other.thread_info;
       
   166             other.thread_info.reset();
       
   167             return *this;
       
   168         }
       
   169 
       
   170         thread&& move()
       
   171         {
       
   172             return static_cast<thread&&>(*this);
       
   173         }
       
   174         
       
   175 #else
       
   176 #ifdef BOOST_NO_SFINAE
       
   177         template <class F>
       
   178         explicit thread(F f):
       
   179             thread_info(make_thread_info(f))
       
   180         {
       
   181             start_thread();
       
   182         }
       
   183 #else
       
   184         template <class F>
       
   185         explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
       
   186             thread_info(make_thread_info(f))
       
   187         {
       
   188             start_thread();
       
   189         }
       
   190 #endif
       
   191         
       
   192         template <class F>
       
   193         explicit thread(detail::thread_move_t<F> f):
       
   194             thread_info(make_thread_info(f))
       
   195         {
       
   196             start_thread();
       
   197         }
       
   198 
       
   199         thread(detail::thread_move_t<thread> x)
       
   200         {
       
   201             thread_info=x->thread_info;
       
   202             x->thread_info.reset();
       
   203         }
       
   204         
       
   205         thread& operator=(detail::thread_move_t<thread> x)
       
   206         {
       
   207             thread new_thread(x);
       
   208             swap(new_thread);
       
   209             return *this;
       
   210         }
       
   211         
       
   212         operator detail::thread_move_t<thread>()
       
   213         {
       
   214             return move();
       
   215         }
       
   216         
       
   217         detail::thread_move_t<thread> move()
       
   218         {
       
   219             detail::thread_move_t<thread> x(*this);
       
   220             return x;
       
   221         }
       
   222 
       
   223 #endif
       
   224 
       
   225         template <class F,class A1>
       
   226         thread(F f,A1 a1):
       
   227             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
       
   228         {
       
   229             start_thread();
       
   230         }
       
   231         template <class F,class A1,class A2>
       
   232         thread(F f,A1 a1,A2 a2):
       
   233             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
       
   234         {
       
   235             start_thread();
       
   236         }
       
   237 
       
   238         template <class F,class A1,class A2,class A3>
       
   239         thread(F f,A1 a1,A2 a2,A3 a3):
       
   240             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
       
   241         {
       
   242             start_thread();
       
   243         }
       
   244 
       
   245         template <class F,class A1,class A2,class A3,class A4>
       
   246         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
       
   247             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
       
   248         {
       
   249             start_thread();
       
   250         }
       
   251 
       
   252         template <class F,class A1,class A2,class A3,class A4,class A5>
       
   253         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
       
   254             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
       
   255         {
       
   256             start_thread();
       
   257         }
       
   258 
       
   259         template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
       
   260         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
       
   261             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
       
   262         {
       
   263             start_thread();
       
   264         }
       
   265 
       
   266         template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
       
   267         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
       
   268             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
       
   269         {
       
   270             start_thread();
       
   271         }
       
   272 
       
   273         template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
       
   274         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
       
   275             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
       
   276         {
       
   277             start_thread();
       
   278         }
       
   279 
       
   280         template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
       
   281         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
       
   282             thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
       
   283         {
       
   284             start_thread();
       
   285         }
       
   286 
       
   287         void swap(thread& x)
       
   288         {
       
   289             thread_info.swap(x.thread_info);
       
   290         }
       
   291 
       
   292         class id;
       
   293         id get_id() const;
       
   294 
       
   295 
       
   296         bool joinable() const;
       
   297         void join();
       
   298         bool timed_join(const system_time& wait_until);
       
   299 
       
   300         template<typename TimeDuration>
       
   301         inline bool timed_join(TimeDuration const& rel_time)
       
   302         {
       
   303             return timed_join(get_system_time()+rel_time);
       
   304         }
       
   305         void detach();
       
   306 
       
   307         static unsigned hardware_concurrency();
       
   308 
       
   309         typedef detail::thread_data_base::native_handle_type native_handle_type;
       
   310         native_handle_type native_handle();
       
   311 
       
   312         // backwards compatibility
       
   313         bool operator==(const thread& other) const;
       
   314         bool operator!=(const thread& other) const;
       
   315 
       
   316         static inline void yield()
       
   317         {
       
   318             this_thread::yield();
       
   319         }
       
   320         
       
   321         static inline void sleep(const system_time& xt)
       
   322         {
       
   323             this_thread::sleep(xt);
       
   324         }
       
   325 
       
   326         // extensions
       
   327         void interrupt();
       
   328         bool interruption_requested() const;
       
   329     };
       
   330 
       
   331     inline void swap(thread& lhs,thread& rhs)
       
   332     {
       
   333         return lhs.swap(rhs);
       
   334     }
       
   335     
       
   336 #ifdef BOOST_HAS_RVALUE_REFS
       
   337     inline thread&& move(thread&& t)
       
   338     {
       
   339         return t;
       
   340     }
       
   341 #else
       
   342     inline thread move(detail::thread_move_t<thread> t)
       
   343     {
       
   344         return thread(t);
       
   345     }
       
   346 #endif
       
   347 
       
   348     namespace this_thread
       
   349     {
       
   350         class BOOST_THREAD_DECL disable_interruption
       
   351         {
       
   352             disable_interruption(const disable_interruption&);
       
   353             disable_interruption& operator=(const disable_interruption&);
       
   354             
       
   355             bool interruption_was_enabled;
       
   356             friend class restore_interruption;
       
   357         public:
       
   358             disable_interruption();
       
   359             ~disable_interruption();
       
   360         };
       
   361 
       
   362         class BOOST_THREAD_DECL restore_interruption
       
   363         {
       
   364             restore_interruption(const restore_interruption&);
       
   365             restore_interruption& operator=(const restore_interruption&);
       
   366         public:
       
   367             explicit restore_interruption(disable_interruption& d);
       
   368             ~restore_interruption();
       
   369         };
       
   370 
       
   371         thread::id BOOST_THREAD_DECL get_id();
       
   372 
       
   373         void BOOST_THREAD_DECL interruption_point();
       
   374         bool BOOST_THREAD_DECL interruption_enabled();
       
   375         bool BOOST_THREAD_DECL interruption_requested();
       
   376 
       
   377         inline void sleep(xtime const& abs_time)
       
   378         {
       
   379             sleep(system_time(abs_time));
       
   380         }
       
   381     }
       
   382 
       
   383     class thread::id
       
   384     {
       
   385     private:
       
   386         detail::thread_data_ptr thread_data;
       
   387             
       
   388         id(detail::thread_data_ptr thread_data_):
       
   389             thread_data(thread_data_)
       
   390         {}
       
   391         friend class thread;
       
   392         friend id this_thread::get_id();
       
   393     public:
       
   394         id():
       
   395             thread_data()
       
   396         {}
       
   397             
       
   398         bool operator==(const id& y) const
       
   399         {
       
   400             return thread_data==y.thread_data;
       
   401         }
       
   402         
       
   403         bool operator!=(const id& y) const
       
   404         {
       
   405             return thread_data!=y.thread_data;
       
   406         }
       
   407         
       
   408         bool operator<(const id& y) const
       
   409         {
       
   410             return thread_data<y.thread_data;
       
   411         }
       
   412         
       
   413         bool operator>(const id& y) const
       
   414         {
       
   415             return y.thread_data<thread_data;
       
   416         }
       
   417         
       
   418         bool operator<=(const id& y) const
       
   419         {
       
   420             return !(y.thread_data<thread_data);
       
   421         }
       
   422         
       
   423         bool operator>=(const id& y) const
       
   424         {
       
   425             return !(thread_data<y.thread_data);
       
   426         }
       
   427 
       
   428         template<class charT, class traits>
       
   429         friend std::basic_ostream<charT, traits>& 
       
   430         operator<<(std::basic_ostream<charT, traits>& os, const id& x)
       
   431         {
       
   432             if(x.thread_data)
       
   433             {
       
   434                 return os<<x.thread_data;
       
   435             }
       
   436             else
       
   437             {
       
   438                 return os<<"{Not-any-thread}";
       
   439             }
       
   440         }
       
   441     };
       
   442 
       
   443     inline bool thread::operator==(const thread& other) const
       
   444     {
       
   445         return get_id()==other.get_id();
       
   446     }
       
   447     
       
   448     inline bool thread::operator!=(const thread& other) const
       
   449     {
       
   450         return get_id()!=other.get_id();
       
   451     }
       
   452         
       
   453     namespace detail
       
   454     {
       
   455         struct thread_exit_function_base
       
   456         {
       
   457             virtual ~thread_exit_function_base()
       
   458             {}
       
   459             virtual void operator()() const=0;
       
   460         };
       
   461         
       
   462         template<typename F>
       
   463         struct thread_exit_function:
       
   464             thread_exit_function_base
       
   465         {
       
   466             F f;
       
   467             
       
   468             thread_exit_function(F f_):
       
   469                 f(f_)
       
   470             {}
       
   471             
       
   472             void operator()() const
       
   473             {
       
   474                 f();
       
   475             }
       
   476         };
       
   477         
       
   478         void add_thread_exit_function(thread_exit_function_base*);
       
   479     }
       
   480     
       
   481     namespace this_thread
       
   482     {
       
   483         template<typename F>
       
   484         void at_thread_exit(F f)
       
   485         {
       
   486             detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
       
   487             detail::add_thread_exit_function(thread_exit_func);
       
   488         }
       
   489     }
       
   490 
       
   491     class thread_group:
       
   492         private noncopyable
       
   493     {
       
   494     public:
       
   495         ~thread_group()
       
   496         {
       
   497             for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
       
   498                 it!=end;
       
   499                 ++it)
       
   500             {
       
   501                 delete *it;
       
   502             }
       
   503         }
       
   504 
       
   505         template<typename F>
       
   506         thread* create_thread(F threadfunc)
       
   507         {
       
   508             boost::lock_guard<mutex> guard(m);
       
   509             std::auto_ptr<thread> new_thread(new thread(threadfunc));
       
   510             threads.push_back(new_thread.get());
       
   511             return new_thread.release();
       
   512         }
       
   513         
       
   514         void add_thread(thread* thrd)
       
   515         {
       
   516             if(thrd)
       
   517             {
       
   518                 boost::lock_guard<mutex> guard(m);
       
   519                 threads.push_back(thrd);
       
   520             }
       
   521         }
       
   522             
       
   523         void remove_thread(thread* thrd)
       
   524         {
       
   525             boost::lock_guard<mutex> guard(m);
       
   526             std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
       
   527             if(it!=threads.end())
       
   528             {
       
   529                 threads.erase(it);
       
   530             }
       
   531         }
       
   532         
       
   533         void join_all()
       
   534         {
       
   535             boost::lock_guard<mutex> guard(m);
       
   536             
       
   537             for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
       
   538                 it!=end;
       
   539                 ++it)
       
   540             {
       
   541                 (*it)->join();
       
   542             }
       
   543         }
       
   544         
       
   545         void interrupt_all()
       
   546         {
       
   547             boost::lock_guard<mutex> guard(m);
       
   548             
       
   549             for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
       
   550                 it!=end;
       
   551                 ++it)
       
   552             {
       
   553                 (*it)->interrupt();
       
   554             }
       
   555         }
       
   556         
       
   557         size_t size() const
       
   558         {
       
   559             boost::lock_guard<mutex> guard(m);
       
   560             return threads.size();
       
   561         }
       
   562         
       
   563     private:
       
   564         std::list<thread*> threads;
       
   565         mutable mutex m;
       
   566     };
       
   567 }
       
   568 
       
   569 #ifdef BOOST_MSVC
       
   570 #pragma warning(pop)
       
   571 #endif
       
   572 
       
   573 #include <boost/config/abi_suffix.hpp>
       
   574 
       
   575 #endif