Changeset 81172


Ignore:
Timestamp:
Nov 4, 2012, 4:47:02 PM (6 years ago)
Author:
viboes
Message:

Thread: Added promise::set_..._at_thread_exit

Location:
trunk
Files:
5 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/boost/thread/detail/config.hpp

    r81145 r81172  
    7474// PROVIDE_PROMISE_LAZY
    7575#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \
    76   && ! defined BOOST_THREAD_PROMISE_LAZY
    77 #define BOOST_THREAD_PROMISE_LAZY
     76  && ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
     77#define BOOST_THREAD_PROVIDES_PROMISE_LAZY
    7878#endif
    7979
  • trunk/boost/thread/future.hpp

    r81152 r81172  
    4040#include <boost/ref.hpp>
    4141#include <boost/scoped_array.hpp>
     42#include <boost/enable_shared_from_this.hpp>
    4243#include <boost/utility/enable_if.hpp>
    4344#include <list>
     
    258259        };
    259260
    260         struct future_object_base
    261         {
     261        struct future_object_base : enable_shared_from_this<future_object_base>
     262        {
     263
    262264            boost::exception_ptr exception;
    263265            bool done;
    264266            bool is_deferred;
     267            bool is_constructed;
    265268#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    266269            bool thread_was_interrupted;
     
    277280            future_object_base():
    278281                done(false),
    279                 is_deferred(false)
     282                is_deferred(false),
     283                is_constructed(false)
    280284#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    281285               , thread_was_interrupted(false)
     
    335339                do_continuation(lock);
    336340            }
     341            void make_ready()
     342            {
     343              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     344              boost::unique_lock<boost::mutex> lock(mutex);
     345              mark_finished_internal(lock);
     346              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     347            }
    337348
    338349            void do_callback(boost::unique_lock<boost::mutex>& lock)
     
    349360            void wait_internal(boost::unique_lock<boost::mutex> &lock, bool rethrow=true)
    350361            {
     362              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    351363              do_callback(lock);
    352               //if (!done)
     364              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     365              //if (!done) // fixme why this doesn't works?
    353366              {
     367                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    354368                if (is_deferred)
    355369                {
     370                  //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    356371                  is_deferred=false;
    357372                  execute(lock);
     373                  //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     374
    358375                  //lock.unlock();
    359376                }
    360377                else
    361378                {
     379                  //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    362380                  while(!done)
    363381                  {
     
    367385                  if(rethrow && thread_was_interrupted)
    368386                  {
     387                    //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    369388                      throw boost::thread_interrupted();
    370389                  }
    371390#endif
     391                  //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    372392                  if(rethrow && exception)
    373393                  {
     394                    //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    374395                      boost::rethrow_exception(exception);
    375396                  }
     
    379400            void wait(bool rethrow=true)
    380401            {
     402              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    381403                boost::unique_lock<boost::mutex> lock(mutex);
     404                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    382405                wait_internal(lock, rethrow);
     406                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    383407            }
    384408
     
    425449            void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock)
    426450            {
     451              //std::cout << "**************"<<__FILE__ << ":" << __LINE__ <<std::endl;
    427452                exception=e;
     453                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    428454                mark_finished_internal(lock);
     455                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    429456            }
    430457            void mark_exceptional_finish()
    431458            {
     459              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    432460                boost::unique_lock<boost::mutex> lock(mutex);
     461                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    433462                mark_exceptional_finish_internal(boost::current_exception(), lock);
     463                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    434464            }
    435465#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     
    441471            }
    442472#endif
     473            void set_exception_at_thread_exit(exception_ptr e)
     474            {
     475              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     476              unique_lock<boost::mutex> lk(mutex);
     477              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     478              if (has_value(lk))
     479              {
     480                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     481                  throw_exception(promise_already_satisfied());
     482              }
     483              //std::cout << "**************"<<__FILE__ << ":" << __LINE__ <<std::endl;
     484              exception=e;
     485              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     486              get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
     487              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     488            }
    443489            bool has_value()
    444490            {
     491              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    445492                boost::lock_guard<boost::mutex> lock(mutex);
    446493                return done && !(exception
     
    450497                );
    451498            }
     499            bool has_value(unique_lock<boost::mutex>& )
     500            {
     501              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     502                return done && !(exception
     503#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     504                    || thread_was_interrupted
     505#endif
     506                );
     507            }
    452508            bool has_exception()
    453509            {
    454510                boost::lock_guard<boost::mutex> lock(mutex);
     511                return done && (exception
     512#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     513                    || thread_was_interrupted
     514#endif
     515                    );
     516            }
     517            bool has_exception(unique_lock<boost::mutex>&)
     518            {
    455519                return done && (exception
    456520#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
     
    597661            move_dest_type get()
    598662            {
     663              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    599664                wait();
     665                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    600666                return static_cast<move_dest_type>(*result);
    601667                //return boost::move(*result); // todo check why this doesn't works (references?)
     
    621687                }
    622688            }
     689
     690
     691            //void set_value_at_thread_exit(source_reference_type result_)
     692            void set_value_at_thread_exit(const T & result_)
     693            {
     694              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     695              unique_lock<boost::mutex> lk(this->mutex);
     696              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     697              if (this->has_value(lk))
     698              {
     699                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     700                  throw_exception(promise_already_satisfied());
     701              }
     702              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     703              future_traits<T>::init(result,result_);
     704              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     705              this->is_constructed = true;
     706              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     707              get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
     708              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     709            }
     710            //void set_value_at_thread_exit(rvalue_source_type result_)
     711            void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_)
     712            {
     713              unique_lock<boost::mutex> lk(this->mutex);
     714              if (this->has_value(lk))
     715                  throw_exception(promise_already_satisfied());
     716              future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
     717              this->is_constructed = true;
     718              get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
     719            }
     720
    623721
    624722        private:
     
    627725        };
    628726
     727        template<typename T>
     728        struct future_object<T&>:
     729            detail::future_object_base
     730        {
     731            typedef typename future_traits<T>::storage_type storage_type;
     732            typedef typename future_traits<T>::source_reference_type source_reference_type;
     733            typedef typename future_traits<T>::rvalue_source_type rvalue_source_type;
     734            typedef typename future_traits<T>::move_dest_type move_dest_type;
     735            typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type;
     736
     737            T* result;
     738
     739            future_object():
     740                result(0)
     741            {}
     742
     743            ~future_object()
     744            {
     745            }
     746
     747            void mark_finished_with_result_internal(T& result_, boost::unique_lock<boost::mutex>& lock)
     748            {
     749                //future_traits<T>::init(result,result_);
     750                result= &result_;
     751                mark_finished_internal(lock);
     752            }
     753
     754//            void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock)
     755//            {
     756//                future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
     757//                mark_finished_internal(lock);
     758//            }
     759
     760            void mark_finished_with_result(T& result_)
     761            {
     762                boost::unique_lock<boost::mutex> lock(mutex);
     763                mark_finished_with_result_internal(result_, lock);
     764            }
     765
     766//            void mark_finished_with_result(rvalue_source_type result_)
     767//            {
     768//                boost::unique_lock<boost::mutex> lock(mutex);
     769//                mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock);
     770//            }
     771
     772
     773            T& get()
     774            {
     775                wait();
     776                //return static_cast<T&>(*result);
     777                return *result;
     778            }
     779
     780            T& get_sh()
     781            {
     782                wait();
     783                //return static_cast<shared_future_get_result_type>(*result);
     784                return *result;
     785            }
     786
     787            // todo move this to detail::future_object_base
     788            future_state::state get_state()
     789            {
     790                boost::lock_guard<boost::mutex> guard(mutex);
     791                if(!done)
     792                {
     793                    return future_state::waiting;
     794                }
     795                else
     796                {
     797                    return future_state::ready;
     798                }
     799            }
     800
     801            void set_value_at_thread_exit(T& result_)
     802            {
     803              unique_lock<boost::mutex> lk(this->mutex);
     804              if (this->has_value(lk))
     805                  throw_exception(promise_already_satisfied());
     806              //future_traits<T>::init(result,result_);
     807              result= &result_;
     808              this->is_constructed = true;
     809              get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
     810            }
     811//            void set_value_at_thread_exit(rvalue_source_type result_)
     812//            {
     813//              unique_lock<boost::mutex> lk(this->mutex);
     814//              if (this->has_value())
     815//                  throw_exception(promise_already_satisfied());
     816//              future_traits<T>::init(result,static_cast<rvalue_source_type>(result_));
     817//              this->is_constructed = true;
     818//              get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
     819//            }
     820
     821
     822        private:
     823            future_object(future_object const&);
     824            future_object& operator=(future_object const&);
     825        };
     826
    629827        template<>
    630828        struct future_object<void>:
     
    649847            void get()
    650848            {
    651                 wait();
     849              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     850                this->wait();
     851                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    652852            }
    653853            void get_sh()
     
    667867                    return future_state::ready;
    668868                }
     869            }
     870            void set_value_at_thread_exit()
     871            {
     872              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     873              unique_lock<boost::mutex> lk(this->mutex);
     874              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     875              if (this->has_value(lk))
     876              {
     877                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     878                  throw_exception(promise_already_satisfied());
     879              }
     880              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     881             this->is_constructed = true;
     882             //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     883              get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
     884              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    669885            }
    670886        private:
     
    12761492        move_dest_type get()
    12771493        {
     1494          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12781495            if(!this->future_)
    12791496            {
     1497              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12801498                boost::throw_exception(future_uninitialized());
    12811499            }
     1500            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12821501#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
     1502            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12831503            future_ptr fut_=this->future_;
     1504            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12841505            this->future_.reset();
     1506            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12851507            return fut_->get();
    12861508#else
     1509            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    12871510            return this->future_->get();
    12881511#endif
     
    14091632        void lazy_init()
    14101633        {
    1411 #if defined BOOST_THREAD_PROMISE_LAZY
     1634#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
    14121635            if(!atomic_load(&future_))
    14131636            {
     
    14331656#endif
    14341657        promise():
    1435 #if defined BOOST_THREAD_PROMISE_LAZY
     1658#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
    14361659            future_(),
    14371660#else
     
    15271750
    15281751        // setting the result with deferred notification
    1529         //void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED
    1530         //void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED
    1531         //void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED
     1752        void set_value_at_thread_exit(const R& r)
     1753        {
     1754          if (future_.get()==0)
     1755          {
     1756              boost::throw_exception(promise_moved());
     1757          }
     1758          future_->set_value_at_thread_exit(r);
     1759        }
     1760
     1761        void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r)
     1762        {
     1763          if (future_.get()==0)
     1764          {
     1765              boost::throw_exception(promise_moved());
     1766          }
     1767          future_->set_value_at_thread_exit(boost::move(r));
     1768        }
     1769        void set_exception_at_thread_exit(exception_ptr e)
     1770        {
     1771          if (future_.get()==0)
     1772          {
     1773              boost::throw_exception(promise_moved());
     1774          }
     1775          future_->set_exception_at_thread_exit(e);
     1776        }
    15321777
    15331778        template<typename F>
     
    15401785    };
    15411786
    1542     template <>
    1543     class promise<void>
    1544     {
    1545         typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
     1787    template <typename R>
     1788    class promise<R&>
     1789    {
     1790        typedef boost::shared_ptr<detail::future_object<R&> > future_ptr;
    15461791
    15471792        future_ptr future_;
     
    15501795        void lazy_init()
    15511796        {
    1552 #if defined BOOST_THREAD_PROMISE_LAZY
     1797#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
    15531798            if(!atomic_load(&future_))
    15541799            {
    15551800                future_ptr blank;
    1556                 atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<void>));
    1557             }
    1558 #endif
    1559         }
     1801                atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R&>));
     1802            }
     1803#endif
     1804        }
     1805
    15601806    public:
    15611807        BOOST_THREAD_MOVABLE_ONLY(promise)
    1562 
    15631808#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
    15641809        template <class Allocator>
    15651810        promise(boost::allocator_arg_t, Allocator a)
    15661811        {
    1567           typedef typename Allocator::template rebind<detail::future_object<void> >::other A2;
     1812          typedef typename Allocator::template rebind<detail::future_object<R&> >::other A2;
    15681813          A2 a2(a);
    15691814          typedef thread_detail::allocator_destructor<A2> D;
    15701815
    1571           future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<void>(), D(a2, 1) );
     1816          future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R&>(), D(a2, 1) );
    15721817          future_obtained = false;
    15731818        }
    15741819#endif
    15751820        promise():
    1576 #if defined BOOST_THREAD_PROMISE_LAZY
     1821#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
    15771822            future_(),
    15781823#else
    1579             future_(new detail::future_object<void>),
     1824            future_(new detail::future_object<R&>()),
    15801825#endif
    15811826            future_obtained(false)
     
    15991844            future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
    16001845        {
    1601           // we need to release the future as shared_ptr doesn't implements move semantics
    16021846            BOOST_THREAD_RV(rhs).future_.reset();
    16031847            BOOST_THREAD_RV(rhs).future_obtained=false;
    16041848        }
    1605 
    16061849        promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
    16071850        {
     
    16201863
    16211864        // Result retrieval
    1622         BOOST_THREAD_FUTURE<void> get_future()
     1865        BOOST_THREAD_FUTURE<R&> get_future()
    16231866        {
    16241867            lazy_init();
    1625 
    16261868            if (future_.get()==0)
    16271869            {
    16281870                boost::throw_exception(promise_moved());
    16291871            }
    1630             if(future_obtained)
     1872            if (future_obtained)
    16311873            {
    16321874                boost::throw_exception(future_already_retrieved());
    16331875            }
    16341876            future_obtained=true;
    1635             return BOOST_THREAD_FUTURE<void>(future_);
    1636         }
    1637 
    1638         void set_value()
     1877            return BOOST_THREAD_FUTURE<R&>(future_);
     1878        }
     1879
     1880        void set_value(R& r)
    16391881        {
    16401882            lazy_init();
     
    16441886                boost::throw_exception(promise_already_satisfied());
    16451887            }
    1646             future_->mark_finished_with_result_internal(lock);
     1888            future_->mark_finished_with_result_internal(r, lock);
    16471889        }
    16481890
     
    16551897                boost::throw_exception(promise_already_satisfied());
    16561898            }
     1899            future_->mark_exceptional_finish_internal(p, lock);
     1900        }
     1901
     1902        // setting the result with deferred notification
     1903        void set_value_at_thread_exit(R& r)
     1904        {
     1905          if (future_.get()==0)
     1906          {
     1907              boost::throw_exception(promise_moved());
     1908          }
     1909          future_->set_value_at_thread_exit(r);
     1910        }
     1911
     1912        void set_exception_at_thread_exit(exception_ptr e)
     1913        {
     1914          if (future_.get()==0)
     1915          {
     1916              boost::throw_exception(promise_moved());
     1917          }
     1918          future_->set_exception_at_thread_exit(e);
     1919        }
     1920
     1921        template<typename F>
     1922        void set_wait_callback(F f)
     1923        {
     1924            lazy_init();
     1925            future_->set_wait_callback(f,this);
     1926        }
     1927
     1928    };
     1929    template <>
     1930    class promise<void>
     1931    {
     1932        typedef boost::shared_ptr<detail::future_object<void> > future_ptr;
     1933
     1934        future_ptr future_;
     1935        bool future_obtained;
     1936
     1937        void lazy_init()
     1938        {
     1939#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
     1940            if(!atomic_load(&future_))
     1941            {
     1942                future_ptr blank;
     1943                atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<void>));
     1944            }
     1945#endif
     1946        }
     1947    public:
     1948        BOOST_THREAD_MOVABLE_ONLY(promise)
     1949
     1950#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS
     1951        template <class Allocator>
     1952        promise(boost::allocator_arg_t, Allocator a)
     1953        {
     1954          typedef typename Allocator::template rebind<detail::future_object<void> >::other A2;
     1955          A2 a2(a);
     1956          typedef thread_detail::allocator_destructor<A2> D;
     1957
     1958          future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<void>(), D(a2, 1) );
     1959          future_obtained = false;
     1960        }
     1961#endif
     1962        promise():
     1963#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
     1964            future_(),
     1965#else
     1966            future_(new detail::future_object<void>),
     1967#endif
     1968            future_obtained(false)
     1969        {}
     1970
     1971        ~promise()
     1972        {
     1973            if(future_)
     1974            {
     1975                boost::unique_lock<boost::mutex> lock(future_->mutex);
     1976
     1977                if(!future_->done)
     1978                {
     1979                    future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
     1980                }
     1981            }
     1982        }
     1983
     1984        // Assignment
     1985        promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT :
     1986            future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained)
     1987        {
     1988          // we need to release the future as shared_ptr doesn't implements move semantics
     1989            BOOST_THREAD_RV(rhs).future_.reset();
     1990            BOOST_THREAD_RV(rhs).future_obtained=false;
     1991        }
     1992
     1993        promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT
     1994        {
     1995            future_=BOOST_THREAD_RV(rhs).future_;
     1996            future_obtained=BOOST_THREAD_RV(rhs).future_obtained;
     1997            BOOST_THREAD_RV(rhs).future_.reset();
     1998            BOOST_THREAD_RV(rhs).future_obtained=false;
     1999            return *this;
     2000        }
     2001
     2002        void swap(promise& other)
     2003        {
     2004            future_.swap(other.future_);
     2005            std::swap(future_obtained,other.future_obtained);
     2006        }
     2007
     2008        // Result retrieval
     2009        BOOST_THREAD_FUTURE<void> get_future()
     2010        {
     2011            lazy_init();
     2012
     2013            if (future_.get()==0)
     2014            {
     2015                boost::throw_exception(promise_moved());
     2016            }
     2017            if(future_obtained)
     2018            {
     2019                boost::throw_exception(future_already_retrieved());
     2020            }
     2021            future_obtained=true;
     2022            return BOOST_THREAD_FUTURE<void>(future_);
     2023        }
     2024
     2025        void set_value()
     2026        {
     2027            lazy_init();
     2028            boost::unique_lock<boost::mutex> lock(future_->mutex);
     2029            if(future_->done)
     2030            {
     2031                boost::throw_exception(promise_already_satisfied());
     2032            }
     2033            future_->mark_finished_with_result_internal(lock);
     2034        }
     2035
     2036        void set_exception(boost::exception_ptr p)
     2037        {
     2038            lazy_init();
     2039            boost::unique_lock<boost::mutex> lock(future_->mutex);
     2040            if(future_->done)
     2041            {
     2042                boost::throw_exception(promise_already_satisfied());
     2043            }
    16572044            future_->mark_exceptional_finish_internal(p,lock);
     2045        }
     2046
     2047        // setting the result with deferred notification
     2048        void set_value_at_thread_exit()
     2049        {
     2050
     2051          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     2052
     2053          if (future_.get()==0)
     2054          {
     2055            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     2056              boost::throw_exception(promise_moved());
     2057          }
     2058          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     2059          future_->set_value_at_thread_exit();
     2060          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     2061        }
     2062
     2063        void set_exception_at_thread_exit(exception_ptr e)
     2064        {
     2065          if (future_.get()==0)
     2066          {
     2067              boost::throw_exception(promise_moved());
     2068          }
     2069          future_->set_exception_at_thread_exit(e);
    16582070        }
    16592071
  • trunk/boost/thread/lockable_traits.hpp

    r81082 r81172  
    99
    1010#include <boost/thread/detail/config.hpp>
    11 #include <boost/thread/detail/move.hpp>
    12 #include <boost/thread/exceptions.hpp>
    13 //#include <boost/thread/testable_mutex.hpp>
    14 #include <boost/thread/thread_time.hpp>
    1511
    1612#include <boost/assert.hpp>
    17 #ifdef BOOST_THREAD_USES_CHRONO
    18 #include <boost/chrono/time_point.hpp>
    19 #include <boost/chrono/duration.hpp>
    20 #endif
    2113#include <boost/detail/workaround.hpp>
    2214#include <boost/type_traits/is_class.hpp>
    23 
    24 #include <algorithm>
    25 #include <iterator>
    2615
    2716#include <boost/config/abi_prefix.hpp>
     
    2918namespace boost
    3019{
     20  namespace sync
     21  {
    3122
    3223#if defined(BOOST_NO_SFINAE) ||                           \
     
    7364        }
    7465
    75         BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock);
    76         BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock);
    77         BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock);
     66      BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock)
     67;      BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock);
     68      BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock);
    7869
    79         template<typename T,bool=has_member_called_lock<T>::value >
    80         struct has_member_lock
     70      template<typename T,bool=has_member_called_lock<T>::value >
     71      struct has_member_lock
     72      {
     73        BOOST_STATIC_CONSTANT(bool, value=false);
     74      };
     75
     76      template<typename T>
     77      struct has_member_lock<T,true>
     78      {
     79        typedef char true_type;
     80        struct false_type
    8181        {
    82             BOOST_STATIC_CONSTANT(bool, value=false);
     82          true_type dummy[2];
    8383        };
    8484
    85         template<typename T>
    86         struct has_member_lock<T,true>
     85        template<typename U,typename V>
     86        static true_type has_member(V (U::*)());
     87        template<typename U>
     88        static false_type has_member(U);
     89
     90        BOOST_STATIC_CONSTANT(
     91            bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
     92      };
     93
     94      template<typename T,bool=has_member_called_unlock<T>::value >
     95      struct has_member_unlock
     96      {
     97        BOOST_STATIC_CONSTANT(bool, value=false);
     98      };
     99
     100      template<typename T>
     101      struct has_member_unlock<T,true>
     102      {
     103        typedef char true_type;
     104        struct false_type
    87105        {
    88             typedef char true_type;
    89             struct false_type
    90             {
    91                 true_type dummy[2];
    92             };
    93 
    94             template<typename U,typename V>
    95             static true_type has_member(V (U::*)());
    96             template<typename U>
    97             static false_type has_member(U);
    98 
    99             BOOST_STATIC_CONSTANT(
    100                 bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type));
     106          true_type dummy[2];
    101107        };
    102108
    103         template<typename T,bool=has_member_called_unlock<T>::value >
    104         struct has_member_unlock
     109        template<typename U,typename V>
     110        static true_type has_member(V (U::*)());
     111        template<typename U>
     112        static false_type has_member(U);
     113
     114        BOOST_STATIC_CONSTANT(
     115            bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
     116      };
     117
     118      template<typename T,bool=has_member_called_try_lock<T>::value >
     119      struct has_member_try_lock
     120      {
     121        BOOST_STATIC_CONSTANT(bool, value=false);
     122      };
     123
     124      template<typename T>
     125      struct has_member_try_lock<T,true>
     126      {
     127        typedef char true_type;
     128        struct false_type
    105129        {
    106             BOOST_STATIC_CONSTANT(bool, value=false);
     130          true_type dummy[2];
    107131        };
    108132
    109         template<typename T>
    110         struct has_member_unlock<T,true>
    111         {
    112             typedef char true_type;
    113             struct false_type
    114             {
    115                 true_type dummy[2];
    116             };
     133        template<typename U>
     134        static true_type has_member(bool (U::*)());
     135        template<typename U>
     136        static false_type has_member(U);
    117137
    118             template<typename U,typename V>
    119             static true_type has_member(V (U::*)());
    120             template<typename U>
    121             static false_type has_member(U);
    122 
    123             BOOST_STATIC_CONSTANT(
    124                 bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type));
    125         };
    126 
    127         template<typename T,bool=has_member_called_try_lock<T>::value >
    128         struct has_member_try_lock
    129         {
    130             BOOST_STATIC_CONSTANT(bool, value=false);
    131         };
    132 
    133         template<typename T>
    134         struct has_member_try_lock<T,true>
    135         {
    136             typedef char true_type;
    137             struct false_type
    138             {
    139                 true_type dummy[2];
    140             };
    141 
    142             template<typename U>
    143             static true_type has_member(bool (U::*)());
    144             template<typename U>
    145             static false_type has_member(U);
    146 
    147             BOOST_STATIC_CONSTANT(
    148                 bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
    149         };
     138        BOOST_STATIC_CONSTANT(
     139            bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type));
     140      };
    150141
    151142    }
    152143
     144    template<typename T>
     145    struct is_basic_lockable
     146    {
     147      BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
     148          detail::has_member_unlock<T>::value);
     149    };
     150    template<typename T>
     151    struct is_lockable
     152    {
     153      BOOST_STATIC_CONSTANT(bool, value =
     154          is_basic_lockable<T>::value &&
     155          detail::has_member_try_lock<T>::value);
     156    };
     157
     158#else
     159    template<typename T>
     160    struct is_basic_lockable
     161    {
     162      BOOST_STATIC_CONSTANT(bool, value = false);
     163    };
     164    template<typename T>
     165    struct is_lockable
     166    {
     167      BOOST_STATIC_CONSTANT(bool, value = false);
     168    };
     169#endif
    153170
    154171    template<typename T>
    155     struct is_mutex_type
     172    struct is_recursive_mutex_sur_parolle
    156173    {
    157         BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
    158                               detail::has_member_unlock<T>::value &&
    159                               detail::has_member_try_lock<T>::value);
     174      BOOST_STATIC_CONSTANT(bool, value = false);
     175    };
    160176
     177    template<typename T>
     178    struct is_recursive_basic_lockable
     179    {
     180      BOOST_STATIC_CONSTANT(bool, value = is_basic_lockable<T>::value &&
     181          is_recursive_mutex_sur_parolle<T>::value);
    161182    };
    162 #else
    163     template<typename T>
    164     struct is_mutex_type
    165     {
    166         BOOST_STATIC_CONSTANT(bool, value = false);
    167     };
    168 #endif
     183  }
     184  template<typename T>
     185  struct is_mutex_type
     186  {
     187    BOOST_STATIC_CONSTANT(bool, value = sync::is_lockable<T>::value);
     188  };
    169189
    170190}
  • trunk/boost/thread/pthread/thread_data.hpp

    r81106 r81172  
    7979    namespace detail
    8080    {
     81        struct future_object_base;
    8182        struct tss_cleanup_function;
    8283        struct thread_exit_callback_node;
     
    120121            notify_list_t notify;
    121122
     123            typedef std::vector<shared_ptr<future_object_base> > async_states_t;
     124            async_states_t async_states_;
     125
    122126            thread_data_base():
    123127                done(false),join_started(false),joined(false),
     
    128132#endif
    129133                current_cond(0),
    130                 notify()
     134                notify(),
     135                async_states_()
    131136            {}
    132137            virtual ~thread_data_base();
     
    139144              notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
    140145            }
     146
     147            void make_ready_at_thread_exit(shared_ptr<future_object_base> as)
     148            {
     149              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     150              async_states_.push_back(as);
     151              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     152            }
     153
    141154        };
    142155
  • trunk/boost/thread/win32/thread_data.hpp

    r81106 r81172  
    7373    namespace detail
    7474    {
     75        struct future_object_base;
    7576        struct tss_cleanup_function;
    7677        struct thread_exit_callback_node;
     
    108109            notify_list_t notify;
    109110
     111            typedef std::vector<shared_ptr<future_object_base> > async_states_t;
     112            async_states_t async_states_;
    110113
    111114            thread_data_base():
     
    119122#endif
    120123                id(0),
    121                 notify()
     124                notify(),
     125                async_states_()
    122126            {}
    123127            virtual ~thread_data_base();
     
    151155            }
    152156
     157            void make_ready_at_thread_exit(shared_ptr<future_object_base> as)
     158            {
     159              async_states_.push_back(as);
     160            }
     161
    153162        };
     163        BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
    154164
    155165        typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
  • trunk/libs/thread/src/pthread/thread.cpp

    r81106 r81172  
    1717#include <boost/thread/tss.hpp>
    1818#include <boost/throw_exception.hpp>
     19#include <boost/thread/future.hpp>
    1920
    2021#ifdef __GLIBC__
     
    3536        thread_data_base::~thread_data_base()
    3637        {
    37           {
    3838            for (notify_list_t::iterator i = notify.begin(), e = notify.end();
    3939                    i != e; ++i)
     
    4242                i->first->notify_all();
    4343            }
    44           }
     44            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     45            for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
     46                    i != e; ++i)
     47            {
     48              //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     49                (*i)->make_ready();
     50                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     51            }
     52            //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     53
    4554        }
    4655
     
    6978                static void tls_destructor(void* data)
    7079                {
     80                  //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    7181                    boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
     82                    //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    7283                    if(thread_info)
    7384                    {
     85                      //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    7486                        while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
    7587                        {
     88                          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     89
    7690                            while(thread_info->thread_exit_callbacks)
    7791                            {
     
    99113                            }
    100114                        }
     115                        //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     116                        if (thread_info) {
     117                          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    101118                        thread_info->self.reset();
     119                        } else{
     120                          //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     121
     122                        }
     123                        //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    102124                    }
     125                    //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
    103126                }
    104127            }
     
    163186// Removed as it stops the debugger identifying the cause of the exception
    164187// Unhandled exceptions still cause the application to terminate
    165 //                 BOOST_CATCH(...)
    166 //                 {
    167 //                     std::terminate();
    168 //                 }
     188                 BOOST_CATCH(...)
     189                 {
     190                   //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     191                   throw;
     192
     193                     std::terminate();
     194                 }
    169195                BOOST_CATCH_END
    170196#endif
     
    174200                thread_info->done=true;
    175201                thread_info->done_condition.notify_all();
     202                //std::cout << __FILE__ << ":" << __LINE__ <<std::endl;
     203
    176204                return 0;
    177205            }
  • trunk/libs/thread/src/win32/thread.cpp

    r81106 r81172  
    1919#include <boost/thread/condition_variable.hpp>
    2020#include <boost/thread/detail/tss_hooks.hpp>
     21#include <boost/thread/future.hpp>
    2122
    2223#include <boost/assert.hpp>
     
    3839    thread_data_base::~thread_data_base()
    3940    {
    40       {
    4141        for (notify_list_t::iterator i = notify.begin(), e = notify.end();
    4242                i != e; ++i)
     
    4545            i->first->notify_all();
    4646        }
    47       }
     47        for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
     48                i != e; ++i)
     49        {
     50            (*i)->make_ready();
     51        }
    4852    }
    4953  }
     54
    5055    namespace
    5156    {
     
    7782        }
    7883
    79         detail::thread_data_base* get_current_thread_data()
    80         {
    81             if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
    82             {
    83                 return 0;
    84             }
    85             return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
    86         }
    87 
    8884        void set_current_thread_data(detail::thread_data_base* new_data)
    8985        {
     
    10096        }
    10197
     98    }
     99    namespace detail
     100    {
     101      thread_data_base* get_current_thread_data()
     102      {
     103          if(current_thread_tls_key==TLS_OUT_OF_INDEXES)
     104          {
     105              return 0;
     106          }
     107          return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key);
     108      }
     109    }
     110    namespace
     111    {
    102112#ifndef BOOST_HAS_THREADEX
    103113// Windows CE doesn't define _beginthreadex
     
    158168        void run_thread_exit_callbacks()
    159169        {
    160             detail::thread_data_ptr current_thread_data(get_current_thread_data(),false);
     170            detail::thread_data_ptr current_thread_data(detail::get_current_thread_data(),false);
    161171            if(current_thread_data)
    162172            {
     
    296306        detail::thread_data_base* get_or_make_current_thread_data()
    297307        {
    298             detail::thread_data_base* current_thread_data(get_current_thread_data());
     308            detail::thread_data_base* current_thread_data(detail::get_current_thread_data());
    299309            if(!current_thread_data)
    300310            {
    301311                make_external_thread_data();
    302                 current_thread_data=get_current_thread_data();
     312                current_thread_data=detail::get_current_thread_data();
    303313            }
    304314            return current_thread_data;
     
    488498            }
    489499#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
    490             if(get_current_thread_data() && get_current_thread_data()->interruption_enabled)
     500            if(detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled)
    491501            {
    492502                interruption_index=handle_count;
    493                 handles[handle_count++]=get_current_thread_data()->interruption_handle;
     503                handles[handle_count++]=detail::get_current_thread_data()->interruption_handle;
    494504            }
    495505#endif
     
    548558                        else if(notified_index==interruption_index)
    549559                        {
    550                             detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
     560                            detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
    551561                            throw thread_interrupted();
    552562                        }
     
    585595            if(interruption_enabled() && interruption_requested())
    586596            {
    587                 detail::win32::ResetEvent(get_current_thread_data()->interruption_handle);
     597                detail::win32::ResetEvent(detail::get_current_thread_data()->interruption_handle);
    588598                throw thread_interrupted();
    589599            }
     
    592602        bool interruption_enabled() BOOST_NOEXCEPT
    593603        {
    594             return get_current_thread_data() && get_current_thread_data()->interruption_enabled;
     604            return detail::get_current_thread_data() && detail::get_current_thread_data()->interruption_enabled;
    595605        }
    596606
    597607        bool interruption_requested() BOOST_NOEXCEPT
    598608        {
    599             return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->interruption_handle,0)==0);
     609            return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0);
    600610        }
    601611#endif
     
    612622            if(interruption_was_enabled)
    613623            {
    614                 get_current_thread_data()->interruption_enabled=false;
     624                detail::get_current_thread_data()->interruption_enabled=false;
    615625            }
    616626        }
     
    618628        disable_interruption::~disable_interruption() BOOST_NOEXCEPT
    619629        {
    620             if(get_current_thread_data())
    621             {
    622                 get_current_thread_data()->interruption_enabled=interruption_was_enabled;
     630            if(detail::get_current_thread_data())
     631            {
     632                detail::get_current_thread_data()->interruption_enabled=interruption_was_enabled;
    623633            }
    624634        }
     
    628638            if(d.interruption_was_enabled)
    629639            {
    630                 get_current_thread_data()->interruption_enabled=true;
     640                detail::get_current_thread_data()->interruption_enabled=true;
    631641            }
    632642        }
     
    634644        restore_interruption::~restore_interruption() BOOST_NOEXCEPT
    635645        {
    636             if(get_current_thread_data())
    637             {
    638                 get_current_thread_data()->interruption_enabled=false;
     646            if(detail::get_current_thread_data())
     647            {
     648                detail::get_current_thread_data()->interruption_enabled=false;
    639649            }
    640650        }
     
    735745    BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
    736746    {
    737       detail::thread_data_base* const current_thread_data(get_current_thread_data());
     747      detail::thread_data_base* const current_thread_data(detail::get_current_thread_data());
    738748      if(current_thread_data)
    739749      {
  • trunk/libs/thread/test/Jamfile.v2

    r81145 r81172  
    268268          [ thread-run2 ./sync/futures/promise/set_value_void_pass.cpp : promise__set_value_void_p ]
    269269          [ thread-run2 ./sync/futures/promise/use_allocator_pass.cpp : promise__use_allocator_p ]
     270          [ thread-run2 ./sync/futures/promise/set_exception_at_thread_exit_pass.cpp : promise__set_exception_at_thread_exit_p ]
     271          [ thread-run2 ./sync/futures/promise/set_lvalue_at_thread_exit_pass.cpp : promise__set_lvalue_at_thread_exit_p ]
     272          [ thread-run2 ./sync/futures/promise/set_rvalue_at_thread_exit_pass.cpp : promise__set_rvalue_at_thread_exit_p ]
     273          [ thread-run2 ./sync/futures/promise/set_value_at_thread_exit_const_pass.cpp : promise__set_value_at_thread_exit_const_p ]
     274          [ thread-run2 ./sync/futures/promise/set_value_at_thread_exit_void_pass.cpp : promise__set_value_at_thread_exit_void_p ]
    270275    ;
    271276
     
    583588    test-suite ts_
    584589    :
     590
    585591          #[ thread-run ../example/unwrap.cpp ]
    586592    ;
  • trunk/libs/thread/test/test_4882.cpp

    r81023 r81172  
    2121    for (int i =0; i<10; ++i)
    2222    {
     23#if 0
    2324      boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(50);
    2425
    2526      if (mutex.timed_lock(timeout))
    2627      {
    27         std::cout << __FILE__ << ":" << __LINE__ << std::endl;
     28        std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
    2829        boost::this_thread::sleep(boost::posix_time::milliseconds(10));
    2930        mutex.unlock();
    30         std::cout << __FILE__ << ":" << __LINE__ << std::endl;
     31        std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
    3132      }
     33#else
     34      boost::chrono::system_clock::time_point timeout = boost::chrono::system_clock::now() + boost::chrono::milliseconds(50);
     35
     36      std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
     37      if (mutex.try_lock_until(timeout))
     38      {
     39        std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
     40        boost::this_thread::sleep_for(boost::chrono::milliseconds(10));
     41        mutex.unlock();
     42        std::cout << __FILE__ << ":" << __LINE__ << " i="<<i << std::endl;
     43      }
     44#endif
    3245    }
    3346  }
Note: See TracChangeset for help on using the changeset viewer.