Ticket #7413: 7413_7575.patch

File 7413_7575.patch, 20.3 KB (added by viboes, 10 years ago)

First implementation on c++11 + pseudo-code for joining the thread

  • boost/thread/pthread/condition_variable.hpp

     
    289289        }
    290290
    291291        template <class lock_type>
    292         inline void wait_until(
     292        cv_status wait_until(
    293293            lock_type& lk,
    294294            chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
    295295        {
     
    299299            seconds s = duration_cast<seconds>(d);
    300300            ts.tv_sec = static_cast<long>(s.count());
    301301            ts.tv_nsec = static_cast<long>((d - s).count());
    302             do_timed_wait(lk, ts);
     302            if (do_timed_wait(lk, ts)) return cv_status::no_timeout;
     303            else return cv_status::timeout;
    303304        }
    304305#endif
    305306
  • boost/thread/pthread/condition_variable_fwd.hpp

     
    212212        void notify_all() BOOST_NOEXCEPT;
    213213
    214214#ifdef BOOST_THREAD_USES_CHRONO
    215         inline void wait_until(
     215        inline cv_status wait_until(
    216216            unique_lock<mutex>& lk,
    217217            chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp)
    218218        {
     
    222222            seconds s = duration_cast<seconds>(d);
    223223            ts.tv_sec = static_cast<long>(s.count());
    224224            ts.tv_nsec = static_cast<long>((d - s).count());
    225             do_timed_wait(lk, ts);
     225            if (do_timed_wait(lk, ts)) return cv_status::no_timeout;
     226            else return cv_status::timeout;
    226227        }
    227228#endif
    228229        //private: // used by boost::thread::try_join_until
  • boost/thread/future.hpp

     
    1818#include <boost/detail/scoped_enum_emulation.hpp>
    1919#include <stdexcept>
    2020#include <boost/thread/detail/move.hpp>
     21#include <boost/thread/detail/async_func.hpp>
    2122#include <boost/thread/thread_time.hpp>
    2223#include <boost/thread/mutex.hpp>
    2324#include <boost/thread/condition_variable.hpp>
     
    4243#include <list>
    4344#include <boost/next_prior.hpp>
    4445#include <vector>
     46
    4547#include <boost/system/error_code.hpp>
    4648#ifdef BOOST_THREAD_USES_CHRONO
    4749#include <boost/chrono/system_clocks.hpp>
     
    206208
    207209    namespace future_state
    208210    {
    209         enum state { uninitialized, waiting, ready, moved };
     211        enum state { uninitialized, waiting, ready, moved, deferred };
    210212    }
    211213
    212214    namespace detail
     
    259261        {
    260262            boost::exception_ptr exception;
    261263            bool done;
     264            bool is_deferred;
    262265#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    263266            bool thread_was_interrupted;
    264267#endif
     
    273276
    274277            future_object_base():
    275278                done(false),
     279                is_deferred(false)
    276280#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    277                 thread_was_interrupted(false)
     281               , thread_was_interrupted(false)
    278282#endif
    279283#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
    280284               , continuation_ptr()
     
    283287            virtual ~future_object_base()
    284288            {}
    285289
     290            void set_deferred() {is_deferred = true;}
     291
    286292            waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv)
    287293            {
    288294                boost::unique_lock<boost::mutex> lock(mutex);
     
    342348
    343349            void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
    344350            {
    345                 do_callback(lock);
    346                 while(!done)
     351              do_callback(lock);
     352              //if (!done)
     353              {
     354                if (is_deferred)
    347355                {
    348                     waiters.wait(lock);
     356                  is_deferred=false;
     357                  execute(lock);
     358                  //lock.unlock();
    349359                }
     360                else
     361                {
     362                  while(!done)
     363                  {
     364                      waiters.wait(lock);
     365                  }
    350366#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    351                 if(rethrow && thread_was_interrupted)
    352                 {
    353                     throw boost::thread_interrupted();
    354                 }
     367                  if(rethrow && thread_was_interrupted)
     368                  {
     369                      throw boost::thread_interrupted();
     370                  }
    355371#endif
    356                 if(rethrow && exception)
    357                 {
    358                     boost::rethrow_exception(exception);
     372                  if(rethrow && exception)
     373                  {
     374                      boost::rethrow_exception(exception);
     375                  }
    359376                }
    360 
     377              }
    361378            }
    362379            void wait(bool rethrow=true)
    363380            {
     
    369386            bool timed_wait_until(boost::system_time const& target_time)
    370387            {
    371388                boost::unique_lock<boost::mutex> lock(mutex);
     389                if (is_deferred)
     390                    return false;
     391
    372392                do_callback(lock);
    373393                while(!done)
    374394                {
     
    388408            wait_until(const chrono::time_point<Clock, Duration>& abs_time)
    389409            {
    390410              boost::unique_lock<boost::mutex> lock(mutex);
     411              if (is_deferred)
     412                  return future_status::deferred;
    391413              do_callback(lock);
    392414              while(!done)
    393415              {
     
    434456#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    435457                    || thread_was_interrupted
    436458#endif
    437 );
     459                    );
    438460            }
    439461
    440462            template<typename F,typename U>
     
    442464            {
    443465                callback=boost::bind(f,boost::ref(*u));
    444466            }
     467            virtual void execute(boost::unique_lock<boost::mutex>&) {}
    445468
    446469        private:
    447470            future_object_base(future_object_base const&);
     
    649672            future_object& operator=(future_object const&);
    650673        };
    651674
     675        /// future_async_object
     676        template<typename Rp, typename Fp>
     677        struct future_async_object: future_object<Rp>
     678        {
     679          typedef future_object<Rp> base_type;
     680          Fp func_;
     681          boost::thread thr_;
     682
     683        public:
     684        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     685          explicit future_async_object(Fp&& f)
     686          : func_(boost::forward<Fp>(f))
     687        #else
     688          explicit future_async_object(Fp f)
     689          : func_(f)
     690        #endif
     691          , thr_(&future_async_object::execute, *this)
     692          {
     693          }
     694
     695          ~future_async_object()
     696          {
     697            thr_.join();
     698          }
     699
     700          virtual void execute(boost::unique_lock<boost::mutex>& lock) {
     701            try
     702            {
     703              this->mark_finished_with_result_internal(func_(), lock);
     704            }
     705            catch (...)
     706            {
     707              this->mark_exceptional_finish_internal(current_exception(), lock);
     708            }
     709
     710          }
     711
     712        };
     713
     714        template<typename Fp>
     715        struct future_async_object<void, Fp>: public future_object<void>
     716        {
     717          typedef future_object<void> base_type;
     718          Fp func_;
     719          boost::thread thr_;
     720
     721        public:
     722        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     723          explicit future_async_object(Fp&& f)
     724          : func_(boost::forward<Fp>(f))
     725        #else
     726          explicit future_async_object(Fp f)
     727          : func_(f)
     728        #endif
     729          , thr_(&future_async_object::execute, *this)
     730          {
     731          }
     732
     733          ~future_async_object()
     734          {
     735            thr_.join();
     736          }
     737
     738          virtual void execute(boost::unique_lock<boost::mutex>& lock) {
     739            try
     740            {
     741              func_();
     742              this->mark_finished_with_result_internal(lock);
     743            }
     744            catch (...)
     745            {
     746              this->mark_exceptional_finish_internal(current_exception(), lock);
     747            }
     748
     749          }
     750
     751        };
     752        /// future_deferred_object
     753        template<typename Rp, typename Fp>
     754        struct future_deferred_object: future_object<Rp>
     755        {
     756          typedef future_object<Rp> base_type;
     757          Fp func_;
     758
     759        public:
     760        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     761          explicit future_deferred_object(Fp&& f)
     762          : func_(boost::forward<Fp>(f))
     763        #else
     764          explicit future_deferred_object(Fp f)
     765          : func_(f)
     766        #endif
     767          {
     768            this->set_deferred();
     769          }
     770
     771          virtual void execute(boost::unique_lock<boost::mutex>& lck) {
     772            try
     773            {
     774              this->mark_finished_with_result_internal(func_(), lck);
     775            }
     776            catch (...)
     777            {
     778              this->mark_exceptional_finish_internal(current_exception(), lck);
     779            }
     780          }
     781        };
     782
     783        template<typename Fp>
     784        struct future_deferred_object<void,Fp>: future_object<void>
     785        {
     786          typedef future_object<void> base_type;
     787          Fp func_;
     788
     789        public:
     790        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     791          explicit future_deferred_object(Fp&& f)
     792          : func_(boost::forward<Fp>(f))
     793        #else
     794          explicit future_deferred_object(Fp f)
     795          : func_(f)
     796        #endif
     797          {
     798            this->set_deferred();
     799          }
     800
     801          virtual void execute(boost::unique_lock<boost::mutex>& lck) {
     802            try
     803            {
     804              func_();
     805              this->mark_finished_with_result_internal(lck);
     806            }
     807            catch (...)
     808            {
     809              this->mark_exceptional_finish_internal(current_exception(), lck);
     810            }
     811          }
     812        };
     813
    652814//        template<typename T, typename Allocator>
    653815//        struct future_object_alloc: public future_object<T>
    654816//        {
     
    10191181    } // detail
    10201182    BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END
    10211183
     1184    namespace detail
     1185    {
     1186        template <class Rp, class Fp>
     1187        BOOST_THREAD_FUTURE<Rp>
     1188        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     1189        make_future_async_object(Fp&& f);
     1190        #else
     1191        make_future_async_object(Fp f);
     1192        #endif
     1193
     1194        template <class Rp, class Fp>
     1195        BOOST_THREAD_FUTURE<Rp>
     1196        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     1197        make_future_deferred_object(Fp&& f);
     1198        #else
     1199        make_future_deferred_object(Fp f);
     1200        #endif
     1201    }
     1202
    10221203    template <typename R>
    10231204    class BOOST_THREAD_FUTURE : public detail::basic_future<R>
    10241205    {
     
    10391220#endif
    10401221        friend class detail::future_waiter;
    10411222
     1223        template <class Rp, class Fp>
     1224        friend BOOST_THREAD_FUTURE<Rp>
     1225        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     1226        detail::make_future_async_object(Fp&& f);
     1227        #else
     1228        detail::make_future_async_object(Fp f);
     1229        #endif
     1230
     1231        template <class Rp, class Fp>
     1232        friend BOOST_THREAD_FUTURE<Rp>
     1233        #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     1234        detail::make_future_deferred_object(Fp&& f);
     1235        #else
     1236        detail::make_future_deferred_object(Fp f);
     1237        #endif
     1238
    10421239        typedef typename detail::future_traits<R>::move_dest_type move_dest_type;
    10431240
    10441241        BOOST_THREAD_FUTURE(future_ptr a_future):
     
    20942291
    20952292    BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END
    20962293
     2294    namespace detail
     2295    {
     2296    ////////////////////////////////
     2297    // make_future_deferred_object
     2298    ////////////////////////////////
     2299    template <class Rp, class Fp>
     2300    BOOST_THREAD_FUTURE<Rp>
     2301    #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     2302    make_future_deferred_object(Fp&& f)
     2303    #else
     2304    make_future_deferred_object(Fp f)
     2305    #endif
     2306    {
     2307      shared_ptr<future_deferred_object<Rp, Fp> >
     2308          h(new future_deferred_object<Rp, Fp>(boost::forward<Fp>(f)));
     2309      return BOOST_THREAD_FUTURE<Rp>(h);
     2310    }
     2311
     2312    ////////////////////////////////
     2313    // make_future_async_object
     2314    ////////////////////////////////
     2315    template <class Rp, class Fp>
     2316    BOOST_THREAD_FUTURE<Rp>
     2317    #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
     2318    make_future_async_object(Fp&& f)
     2319    #else
     2320    make_future_async_object(Fp f)
     2321    #endif
     2322    {
     2323      shared_ptr<future_async_object<Rp, Fp> >
     2324          h(new future_async_object<Rp, Fp>(boost::forward<Fp>(f)));
     2325      return BOOST_THREAD_FUTURE<Rp>(h);
     2326    }
     2327
     2328    }
     2329
     2330    ////////////////////////////////
     2331    // template <class F, class... ArgTypes>
     2332    // future<R> async(F&&, ArgTypes&&...);
     2333    ////////////////////////////////
     2334
    20972335#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR
    20982336
    20992337#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK
     
    21642402              typename decay<ArgTypes>::type...
    21652403          )>::type R;
    21662404          typedef packaged_task<R(ArgTypes...)> packaged_task_type;
     2405
     2406          typedef detail::async_func<typename decay<F>::type, typename decay<ArgTypes>::type...> BF;
     2407          typedef typename BF::result_type Rp;
     2408
    21672409  #else
    21682410        template <class F>
    21692411        BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type>
     
    21712413        {
    21722414          typedef typename boost::result_of<typename decay<F>::type()>::type R;
    21732415          typedef packaged_task<R()> packaged_task_type;
     2416
     2417          typedef detail::async_func<typename decay<F>::type> BF;
     2418          typedef typename BF::result_type Rp;
     2419
    21742420  #endif
    21752421#else
    21762422        template <class F>
     
    21792425        {
    21802426          typedef typename boost::result_of<typename decay<F>::type()>::type R;
    21812427          typedef packaged_task<R> packaged_task_type;
     2428
     2429          typedef detail::async_func<typename decay<F>::type> BF;
     2430          typedef typename BF::result_type Rp;
    21822431#endif
    21832432
    21842433        if (int(policy) & int(launch::async))
     
    21952444        }
    21962445        else if (int(policy) & int(launch::deferred))
    21972446        {
    2198           packaged_task_type pt( boost::forward<F>(f) );
     2447#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
     2448          return boost::detail::make_future_deferred_object<Rp>(
     2449              BF(
     2450                  thread_detail::decay_copy(boost::forward<F>(f))
     2451                  , thread_detail::decay_copy(boost::forward<ArgTypes>(args))...
     2452              )
     2453          );
     2454#else
     2455              BOOST_THREAD_FUTURE<R> ret;
     2456              return ::boost::move(ret);
     2457//          return boost::detail::make_future_deferred_object<Rp>(
     2458//              BF(
     2459//                  thread_detail::decay_copy(boost::forward<F>(f))
     2460//              )
     2461//          );
     2462#endif
    21992463
    2200           BOOST_THREAD_FUTURE<R> ret = pt.get_future();
    2201           return ::boost::move(ret);
    22022464        } else {
    22032465          BOOST_THREAD_FUTURE<R> ret;
    22042466          return ::boost::move(ret);
     
    22112473        return async(launch::any, boost::forward<F>(f));
    22122474    }
    22132475
     2476
     2477  ////////////////////////////////
     2478  // make_future
     2479  ////////////////////////////////
    22142480  template <typename T>
    22152481  BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value)
    22162482  {
     
    22282494
    22292495  }
    22302496
     2497  ////////////////////////////////
     2498  // make_shared_future
     2499  ////////////////////////////////
    22312500  template <typename T>
    22322501  shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value)
    22332502  {
     
    22452514
    22462515  }
    22472516
     2517  ////////////////////////////////
     2518  // detail::future_continuation
     2519  ////////////////////////////////
    22482520#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
    22492521  namespace detail
    22502522  {
     
    23182590#endif
    23192591  }
    23202592
    2321 //        template<typename F>
    2322 //        auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
     2593  ////////////////////////////////
     2594  // template<typename F>
     2595  // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>;
     2596  ////////////////////////////////
    23232597
    23242598  template <typename R>
    23252599  template <typename F>
  • boost/thread/detail/move.hpp

     
    230230
    231231
    232232
    233 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
    234233namespace boost
    235234{  namespace thread_detail
    236235  {
     236#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
    237237      template <class T>
    238238      typename decay<T>::type
    239239      decay_copy(T&& t)
    240240      {
    241241          return boost::forward<T>(t);
    242242      }
     243#else
     244  template <class T>
     245  typename decay<T>::type
     246  decay_copy(BOOST_THREAD_FWD_REF(T) t)
     247  {
     248      return boost::forward<T>(t);
    243249  }
     250#endif
     251  }
    244252}
    245 #endif
    246253
    247254#include <boost/config/abi_suffix.hpp>
    248255
  • libs/thread/test/sync/futures/async/async_pass.cpp

     
    145145    Clock::time_point t1 = Clock::now();
    146146    BOOST_TEST(t1 - t0 < ms(100));
    147147  }
    148 //  {
    149 //    boost::future<int> f = boost::async(boost::launch::deferred, f0);
    150 //    boost::this_thread::sleep_for(ms(300));
    151 //    Clock::time_point t0 = Clock::now();
    152 //    BOOST_TEST(f.get() == 3);
    153 //    Clock::time_point t1 = Clock::now();
    154 //    BOOST_TEST(t1 - t0 > ms(100));
    155 //  }
    156 //
     148#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
    157149  {
     150    boost::future<int> f = boost::async(boost::launch::deferred, f0);
     151    boost::this_thread::sleep_for(ms(300));
     152    Clock::time_point t0 = Clock::now();
     153    BOOST_TEST(f.get() == 3);
     154    Clock::time_point t1 = Clock::now();
     155    BOOST_TEST(t1 - t0 > ms(100));
     156  }
     157#endif
     158  {
    158159    boost::future<int&> f = boost::async(f1);
    159160    boost::this_thread::sleep_for(ms(300));
    160161    Clock::time_point t0 = Clock::now();
     
    178179    Clock::time_point t1 = Clock::now();
    179180    BOOST_TEST(t1 - t0 < ms(100));
    180181  }
    181 //  {
    182 //    boost::future<int&> f = boost::async(boost::launch::deferred, f1);
    183 //    boost::this_thread::sleep_for(ms(300));
    184 //    Clock::time_point t0 = Clock::now();
    185 //    BOOST_TEST(&f.get() == &i);
    186 //    Clock::time_point t1 = Clock::now();
    187 //    BOOST_TEST(t1 - t0 > ms(100));
    188 //  }
    189 //
     182#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
    190183  {
     184    boost::future<int&> f = boost::async(boost::launch::deferred, f1);
     185    boost::this_thread::sleep_for(ms(300));
     186    Clock::time_point t0 = Clock::now();
     187    BOOST_TEST(&f.get() == &i);
     188    Clock::time_point t1 = Clock::now();
     189    BOOST_TEST(t1 - t0 > ms(100));
     190  }
     191#endif
     192  {
    191193    boost::future<void> f = boost::async(f2);
    192194    boost::this_thread::sleep_for(ms(300));
    193195    Clock::time_point t0 = Clock::now();
     
    211213    Clock::time_point t1 = Clock::now();
    212214    BOOST_TEST(t1 - t0 < ms(100));
    213215  }
    214 //  {
    215 //    boost::future<void> f = boost::async(boost::launch::deferred, f2);
    216 //    boost::this_thread::sleep_for(ms(300));
    217 //    Clock::time_point t0 = Clock::now();
    218 //    f.get();
    219 //    Clock::time_point t1 = Clock::now();
    220 //    BOOST_TEST(t1 - t0 > ms(100));
    221 //  }
     216#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
     217  {
     218    boost::future<void> f = boost::async(boost::launch::deferred, f2);
     219    boost::this_thread::sleep_for(ms(300));
     220    Clock::time_point t0 = Clock::now();
     221    f.get();
     222    Clock::time_point t1 = Clock::now();
     223    BOOST_TEST(t1 - t0 > ms(100));
     224  }
     225#endif
     226
     227  // todo fixme
    222228#if 0 && defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
    223229  {
    224230    boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(boost::launch::async, &f3, 3);
     
    230236  }
    231237#endif
    232238
     239  // todo fixme
    233240#if 0 && defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
    234241  {
    235242    boost::future<boost::interprocess::unique_ptr<int, boost::default_delete<int> > > f = boost::async(&f4, boost::interprocess::unique_ptr<int, boost::default_delete<int> >(new int(3)));