Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84717 - in branches/release: boost/thread boost/thread/win32 libs/thread libs/thread/doc libs/thread/src/win32 libs/thread/test/sync/futures/promise libs/thread/test/threads/thread/constr
From: vicente.botet_at_[hidden]
Date: 2013-06-09 13:18:15


Author: viboes
Date: 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013)
New Revision: 84717
URL: http://svn.boost.org/trac/boost/changeset/84717

Log:
Thread: fix #8550, #8671, #8672.

Added:
   branches/release/boost/thread/win32/mfc_thread_init.hpp
      - copied unchanged from r84684, trunk/boost/thread/win32/mfc_thread_init.hpp
Properties modified:
   branches/release/boost/thread/ (props changed)
   branches/release/libs/thread/ (props changed)
Text files modified:
   branches/release/boost/thread/future.hpp | 27 ++++++++++----------
   branches/release/boost/thread/win32/mfc_thread_init.hpp | 41 ++++++++++++++++++++++++++++++++
   branches/release/libs/thread/doc/changes.qbk | 3 ++
   branches/release/libs/thread/src/win32/tss_pe.cpp | 41 ++++++++++++++++++++++++++++++++
   branches/release/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp | 19 +++++++++++---
   branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp | 25 ++++++++++++++++---
   branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp | 4 ++
   branches/release/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp | 51 ++++++++++++++++++++++++++++++++++++++++
   8 files changed, 189 insertions(+), 22 deletions(-)

Modified: branches/release/boost/thread/future.hpp
==============================================================================
--- branches/release/boost/thread/future.hpp Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/boost/thread/future.hpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -443,6 +443,7 @@
                   throw_exception(promise_already_satisfied());
               }
               exception=e;
+ this->is_constructed = true;
               get_current_thread_data()->make_ready_at_thread_exit(shared_from_this());
             }
             bool has_value()
@@ -1746,7 +1747,7 @@
             {
                 boost::unique_lock<boost::mutex> lock(future_->mutex);
 
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
                 {
                     future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
                 }
@@ -1915,7 +1916,7 @@
             {
                 boost::unique_lock<boost::mutex> lock(future_->mutex);
 
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
                 {
                     future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
                 }
@@ -2057,7 +2058,7 @@
             {
                 boost::unique_lock<boost::mutex> lock(future_->mutex);
 
- if(!future_->done)
+ if(!future_->done && !future_->is_constructed)
                 {
                     future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock);
                 }
@@ -3469,7 +3470,7 @@
       boost::thread thr_;
 
     public:
- explicit future_async_continuation(
+ future_async_continuation(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ) :
       parent(f.future_),
@@ -3532,15 +3533,15 @@
     struct future_async_continuation<F, void, Fp>: public future_object<void>
     {
       typedef future_object<void> base_type;
- F& parent;
+ F parent;
       Fp continuation;
       boost::thread thr_;
 
     public:
- explicit future_async_continuation(
+ future_async_continuation(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ) :
- parent(f),
+ parent(f.future_),
       continuation(boost::move(c)),
       thr_()
       {
@@ -3590,14 +3591,14 @@
     struct future_deferred_continuation: future_object<Rp>
     {
       typedef future_object<Rp> base_type;
- F& parent;
+ F parent;
       Fp continuation;
 
     public:
- explicit future_deferred_continuation(
+ future_deferred_continuation(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ) :
- parent(f),
+ parent(f.future_),
           //continuation(boost::move(c))
           continuation(c)
       {
@@ -3625,14 +3626,14 @@
     struct future_deferred_continuation<F,void,Fp>: future_object<void>
     {
       typedef future_object<void> base_type;
- F& parent;
+ F parent;
       Fp continuation;
 
     public:
- explicit future_deferred_continuation(
+ future_deferred_continuation(
           F& f, BOOST_THREAD_FWD_REF(Fp) c
           ):
- parent(f),
+ parent(f.future_),
           continuation(boost::move(c))
       {
         this->set_deferred();

Copied: branches/release/boost/thread/win32/mfc_thread_init.hpp (from r84684, trunk/boost/thread/win32/mfc_thread_init.hpp)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/release/boost/thread/win32/mfc_thread_init.hpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717, copy of r84684, trunk/boost/thread/win32/mfc_thread_init.hpp)
@@ -0,0 +1,41 @@
+#ifndef BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP
+#define BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// (C) Copyright 2008 Anthony Williams
+// (C) Copyright 2011-2012 Vicente J. Botet Escriba
+
+
+// check if we use MFC
+#ifdef _AFXDLL
+# if defined(_AFXEXT)
+
+// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain
+extern "C"
+inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ // save critical data pointers before running the constructors
+ AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
+ pModuleState->m_pClassInit = pModuleState->m_classList;
+ pModuleState->m_pFactoryInit = pModuleState->m_factoryList;
+ pModuleState->m_classList.m_pHead = NULL;
+ pModuleState->m_factoryList.m_pHead = NULL;
+ }
+ return TRUE; // ok
+}
+
+extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain;
+
+# elif defined(_USRDLL)
+
+extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID);
+extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain;
+
+# endif
+#endif
+
+
+#endif

Modified: branches/release/libs/thread/doc/changes.qbk
==============================================================================
--- branches/release/libs/thread/doc/changes.qbk Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/libs/thread/doc/changes.qbk 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -53,10 +53,13 @@
 * [@http://svn.boost.org/trac/boost/ticket/8443 #8443] Header file inclusion order may cause crashes
 * [@http://svn.boost.org/trac/boost/ticket/8451 #8451] Missing documented function 'boost::scoped_thread::joinable'
 * [@http://svn.boost.org/trac/boost/ticket/8530 #8530] [Coverity] Unused variable thread_handle, uninitialized variable cond_mutex in thread/pthread/thread_data.hpp
+* [@http://svn.boost.org/trac/boost/ticket/8550 #8550] static linking of Boost.Thread with an MFC-Dll
 * [@http://svn.boost.org/trac/boost/ticket/8576 #8576] "sur parolle" should be "sur parole".
 * [@http://svn.boost.org/trac/boost/ticket/8596 #8596] With C++0x enabled, boost::packaged_task stores a reference to function objects, instead of a copy.
 * [@http://svn.boost.org/trac/boost/ticket/8626 #8626] Reintroduce BOOST_VERIFY on pthread_mutex_destroy return type
 * [@http://svn.boost.org/trac/boost/ticket/8645 #8645] Typo in Strict lock definition
+* [@http://svn.boost.org/trac/boost/ticket/8671 #8671] promise: set_..._at_thread_exit
+* [@http://svn.boost.org/trac/boost/ticket/8672 #8672] future<>::then(void()) doesn't works
 
 [heading Version 4.0.0 - boost 1.53]
 

Modified: branches/release/libs/thread/src/win32/tss_pe.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/tss_pe.cpp Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/libs/thread/src/win32/tss_pe.cpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -80,6 +80,36 @@
     #define WIN32_LEAN_AND_MEAN
     #include <windows.h>
 
+
+// _pRawDllMainOrig can be defined by including boost/thread/win32/mfc_thread_init.hpp
+// into your dll; it ensures that MFC-Dll-initialization will be done properly
+// The following code is adapted from the MFC-Dll-init code
+/*
+ * _pRawDllMainOrig MUST be an extern const variable, which will be aliased to
+ * _pDefaultRawDllMainOrig if no real user definition is present, thanks to the
+ * alternatename directive.
+ */
+
+// work at least with _MSC_VER 1500 (MSVC++ 9.0, VS 2008)
+#if (_MSC_VER >= 1500)
+
+extern "C" {
+extern BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID);
+extern BOOL (WINAPI * const _pDefaultRawDllMainOrig)(HANDLE, DWORD, LPVOID) = NULL;
+#if defined (_M_IX86)
+#pragma comment(linker, "/alternatename:__pRawDllMainOrig=__pDefaultRawDllMainOrig")
+#elif defined (_M_X64) || defined (_M_ARM)
+#pragma comment(linker, "/alternatename:_pRawDllMainOrig=_pDefaultRawDllMainOrig")
+#else /* defined (_M_X64) || defined (_M_ARM) */
+#error Unsupported platform
+#endif /* defined (_M_X64) || defined (_M_ARM) */
+}
+
+#endif
+
+
+
+
     //Definitions required by implementation
 
     #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
@@ -240,7 +270,11 @@
             }
         }
 
+#if (_MSC_VER >= 1500)
+ BOOL WINAPI dll_callback(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
+#else
         BOOL WINAPI dll_callback(HANDLE, DWORD dwReason, LPVOID)
+#endif
         {
             switch (dwReason)
             {
@@ -251,6 +285,13 @@
                 boost::on_process_exit();
                 break;
             }
+
+#if (_MSC_VER >= 1500)
+ if( _pRawDllMainOrig )
+ {
+ return _pRawDllMainOrig(hInstance, dwReason, lpReserved);
+ }
+#endif
             return true;
         }
     } //namespace

Modified: branches/release/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/libs/thread/test/sync/futures/promise/set_exception_at_thread_exit_pass.cpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -44,10 +44,14 @@
   }
 }
 
-//void func(boost::promise<int> p)
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+void func(boost::promise<int> p)
+#else
 boost::promise<int> p;
 void func()
+#endif
 {
+ //p.set_exception(boost::make_exception_ptr(3));
   p.set_exception_at_thread_exit(boost::make_exception_ptr(3));
 }
 
@@ -55,10 +59,14 @@
 {
   {
     typedef int T;
- //boost::promise<T> p;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::promise<T> p;
+ boost::future<T> f = p.get_future();
+ boost::thread(func, boost::move(p)).detach();
+#else
     boost::future<T> f = p.get_future();
- //boost::thread(func, boost::move(p)).detach();
     boost::thread(func).detach();
+#endif
     try
     {
       f.get();
@@ -77,9 +85,12 @@
     typedef int T;
     boost::promise<T> p2;
     boost::future<T> f = p2.get_future();
- //boost::thread(func, boost::move(p)).detach();
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::thread(func, boost::move(p2)).detach();
+#else
     p = boost::move(p2);
     boost::thread(func).detach();
+#endif
     try
     {
       f.get();

Modified: branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_const_pass.cpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -23,9 +23,12 @@
 #include <boost/thread/future.hpp>
 #include <boost/detail/lightweight_test.hpp>
 
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+void func(boost::promise<int> p)
+#else
 boost::promise<int> p;
-//void func(boost::promise<int> p)
 void func()
+#endif
 {
   const int i = 5;
   p.set_value_at_thread_exit(i);
@@ -34,18 +37,32 @@
 int main()
 {
   {
- //boost::promise<int> p;
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+ boost::promise<int> p;
+ boost::future<int> f = p.get_future();
+ boost::thread(func, boost::move(p)).detach();
+#else
     boost::future<int> f = p.get_future();
- //boost::thread(func, boost::move(p)).detach();
     boost::thread(func).detach();
- BOOST_TEST(f.get() == 5);
+#endif
+ try
+ {
+ BOOST_TEST(f.get() == 5);
+ }
+ catch (...)
+ {
+ BOOST_TEST(false);
+ }
   }
   {
+#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
+#else
     boost::promise<int> p2;
     boost::future<int> f = p2.get_future();
     p = boost::move(p2);
     boost::thread(func).detach();
     BOOST_TEST(f.get() == 5);
+#endif
   }
   return boost::report_errors();
 }

Modified: branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/libs/thread/test/sync/futures/promise/set_value_at_thread_exit_void_pass.cpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -32,7 +32,8 @@
   i = 1;
 }
 
-void func2_mv(BOOST_THREAD_RV_REF(boost::promise<void>) p2)
+//void func2_mv(BOOST_THREAD_RV_REF(boost::promise<void>) p2)
+void func2_mv(boost::promise<void> p2)
 {
   p2.set_value_at_thread_exit();
   i = 2;
@@ -92,6 +93,7 @@
     boost::thread(func2, &p2).detach();
 #endif
     f.wait();
+ f.get();
     BOOST_TEST(i == 2);
   }
   catch(std::exception& ex)

Modified: branches/release/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp
==============================================================================
--- branches/release/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp Sun Jun 9 12:18:38 2013 (r84716)
+++ branches/release/libs/thread/test/threads/thread/constr/FrvalueArgs_pass.cpp 2013-06-09 13:18:15 EDT (Sun, 09 Jun 2013) (r84717)
@@ -40,6 +40,51 @@
   }
 };
 
+class M
+{
+
+public:
+ long data_;
+ static int n_moves;
+
+ BOOST_THREAD_MOVABLE_ONLY(M)
+ static void reset() {
+ n_moves=0;
+ }
+ explicit M(long i) : data_(i)
+ {
+ }
+ M(BOOST_THREAD_RV_REF(M) a) : data_(BOOST_THREAD_RV(a).data_)
+ {
+ BOOST_THREAD_RV(a).data_ = -1;
+ ++n_moves;
+ }
+ M& operator=(BOOST_THREAD_RV_REF(M) a)
+ {
+ data_ = BOOST_THREAD_RV(a).data_;
+ BOOST_THREAD_RV(a).data_ = -1;
+ ++n_moves;
+ return *this;
+ }
+ ~M()
+ {
+ }
+
+ void operator()(int) const
+ { }
+ long operator()() const
+ { return data_;}
+ long operator()(long i, long j) const
+ { return data_ + i + j;}
+};
+
+int M::n_moves = 0;
+
+void fct(BOOST_THREAD_RV_REF(M) v)
+{
+ BOOST_TEST_EQ(v.data_, 1);
+}
+
 int main()
 {
 #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
@@ -47,6 +92,12 @@
     boost::thread t = boost::thread( MoveOnly(), MoveOnly() );
     t.join();
   }
+ {
+ M::reset();
+ boost::thread t = boost::thread( fct, M(1) );
+ t.join();
+ BOOST_TEST_EQ(M::n_moves, 2);
+ }
 #endif
   return boost::report_errors();
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk