8 changes: 5 additions & 3 deletions include/boost/thread/csbl/devector.hpp
Expand Up @@ -21,8 +21,8 @@ namespace boost
template <class T>
class devector
{
typedef vector<T> vector_type;
vector<T> data_;
typedef csbl::vector<T> vector_type;
vector_type data_;
std::size_t front_index_;

BOOST_COPYABLE_AND_MOVABLE(devector)
Expand Down Expand Up @@ -58,7 +58,9 @@ namespace boost
}

devector& operator=(BOOST_RV_REF(devector) x)
BOOST_NOEXCEPT_IF(vector<T>::allocator_traits_type::propagate_on_container_move_assignment::value)
#if defined BOOST_THREAD_USES_BOOST_VECTOR
BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value)
#endif
{
data_ = boost::move(x.data_);
front_index_ = x.front_index_;
Expand Down
1 change: 0 additions & 1 deletion include/boost/thread/detail/thread.hpp
Expand Up @@ -173,7 +173,6 @@ namespace boost
private:
bool start_thread_noexcept();
bool start_thread_noexcept(const attributes& attr);
//public:
void start_thread()
{
if (!start_thread_noexcept())
Expand Down
14 changes: 7 additions & 7 deletions include/boost/thread/executors/basic_thread_pool.hpp
Expand Up @@ -13,7 +13,7 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/concurrent_queues/sync_queue.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/thread/csbl/vector.hpp>
Expand All @@ -30,15 +30,14 @@ namespace executors
/// type-erasure to store the works to do
typedef executors::work work;
private:
/// the kind of stored threads are scoped threads to ensure that the threads are joined.
typedef thread thread_t;
/// A move aware vector type
typedef scoped_thread<> thread_t;
typedef csbl::vector<thread_t> thread_vector;

/// the thread safe work queue
concurrent::sync_queue<work > work_queue;
/// A move aware vector
thread_vector threads;
/// the thread safe work queue
concurrent::sync_queue<work > work_queue;

public:
/**
Expand All @@ -61,7 +60,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
/**
Expand Down Expand Up @@ -222,7 +221,8 @@ namespace executors
{
// signal to all the worker threads that there will be no more submissions.
close();
// joins all the threads as the threads were scoped_threads
// joins all the threads before destroying the thread pool resources (e.g. the queue).
join();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion include/boost/thread/executors/loop_executor.hpp
Expand Up @@ -54,7 +54,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
private:
Expand Down
2 changes: 1 addition & 1 deletion include/boost/thread/executors/serial_executor.hpp
Expand Up @@ -82,7 +82,7 @@ namespace executors
catch (...)
{
std::terminate();
return false;
//return false;
}
}
private:
Expand Down
Expand Up @@ -53,7 +53,7 @@ BOOST_THREAD_INLINE_NAMESPACE(v2)
throw;
}
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
catch (task_canceled_exception& ex)
catch (task_canceled_exception&)
{
}
#endif
Expand Down
247 changes: 154 additions & 93 deletions include/boost/thread/future.hpp

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions include/boost/thread/poly_lockable.hpp
Expand Up @@ -31,7 +31,7 @@ namespace boost
//]

//[poly_lockable
class poly_lockable : public basic_poly_lockable<Lockable>
class poly_lockable : public basic_poly_lockable
{
public:

Expand All @@ -41,7 +41,7 @@ namespace boost
//]

//[timed_poly_lockable
class timed_poly_lockable: public poly_lockable<TimedLock>
class timed_poly_lockable: public poly_lockable
{
public:
virtual ~timed_poly_lockable()=0;
Expand Down
21 changes: 21 additions & 0 deletions include/boost/thread/pthread/condition_variable_fwd.hpp
Expand Up @@ -120,6 +120,15 @@ namespace boost
unique_lock<mutex>& m,
duration_type const& wait_duration)
{
if (wait_duration.is_pos_infinity())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
}
if (wait_duration.is_special())
{
return true;
}
return timed_wait(m,get_system_time()+wait_duration);
}

Expand Down Expand Up @@ -149,6 +158,18 @@ namespace boost
unique_lock<mutex>& m,
duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
return timed_wait(m,get_system_time()+wait_duration,pred);
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions include/boost/thread/pthread/once_atomic.hpp
Expand Up @@ -214,7 +214,7 @@ namespace boost
thread_detail::commit_once_region(flag);
}
}

#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
template<typename Function>
inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f)
{
Expand Down Expand Up @@ -302,7 +302,7 @@ namespace boost
}
}


#endif // __SUNPRO_CC

#endif
}
Expand Down
1 change: 1 addition & 0 deletions include/boost/thread/shared_mutex.hpp
Expand Up @@ -28,6 +28,7 @@

namespace boost
{
typedef shared_mutex shared_timed_mutex;
namespace sync
{
#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES
Expand Down
16 changes: 14 additions & 2 deletions include/boost/thread/win32/condition_variable.hpp
Expand Up @@ -339,8 +339,8 @@ namespace boost
{
if (wait_duration.is_pos_infinity())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
wait(m); // or do_wait(m,detail::timeout::sentinel());
return true;
}
if (wait_duration.is_special())
{
Expand All @@ -362,6 +362,18 @@ namespace boost
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
#endif
Expand Down
42 changes: 21 additions & 21 deletions include/boost/thread/win32/thread_primitives.hpp
Expand Up @@ -46,7 +46,7 @@ namespace boost
unsigned const create_event_manual_reset = 0x00000001;
unsigned const event_all_access = EVENT_ALL_ACCESS;
unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;


# ifdef BOOST_NO_ANSI_APIS
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
Expand All @@ -59,7 +59,7 @@ namespace boost
using ::CreateSemaphoreExW;
# endif
using ::OpenEventW;
using ::GetModuleGandleW;
using ::GetModuleHandleW;
# else
using ::CreateMutexA;
using ::CreateEventA;
Expand All @@ -79,8 +79,8 @@ namespace boost
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
Expand All @@ -91,7 +91,7 @@ namespace boost
using ::Sleep;
using ::QueueUserAPC;
using ::GetProcAddress;
#endif
#endif
}
}
}
Expand Down Expand Up @@ -286,7 +286,7 @@ namespace boost
}

// Oops, we weren't called often enough, we're stuck
return 0xFFFFFFFF;
return 0xFFFFFFFF;
}
#else
#endif
Expand All @@ -295,12 +295,12 @@ namespace boost
static detail::gettickcount64_t gettickcount64impl;
if(gettickcount64impl)
return gettickcount64impl;

// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
// and kernel32 isn't used in Windows Phone.
#if BOOST_PLAT_WINDOWS_RUNTIME
gettickcount64impl = &GetTickCount64;
#else
#else
farproc_t addr=GetProcAddress(
#if !defined(BOOST_NO_ANSI_APIS)
GetModuleHandleA("KERNEL32.DLL"),
Expand All @@ -312,7 +312,7 @@ namespace boost
gettickcount64impl=(detail::gettickcount64_t) addr;
else
gettickcount64impl=&GetTickCount64emulation;
#endif
#endif
return gettickcount64impl;
}

Expand Down Expand Up @@ -343,14 +343,14 @@ namespace boost
handle const res = win32::CreateEventW(0, type, state, mutex_name);
#else
handle const res = win32::CreateEventExW(
0,
mutex_name,
0,
mutex_name,
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
event_all_access);
#endif
return res;
}

inline handle create_anonymous_event(event_type type,initial_event_state state)
{
handle const res = create_event(0, type, state);
Expand All @@ -374,7 +374,7 @@ namespace boost
#endif
return res;
}

inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
Expand Down Expand Up @@ -402,20 +402,20 @@ namespace boost
{
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
}

inline void get_system_info(system_info *info)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
win32::GetNativeSystemInfo(info);
win32::GetNativeSystemInfo(info);
#else
win32::GetSystemInfo(info);
#endif
}

inline void sleep(unsigned long milliseconds)
{
if(milliseconds == 0)
{
{
#if BOOST_PLAT_WINDOWS_RUNTIME
std::this_thread::yield();
#else
Expand All @@ -425,13 +425,13 @@ namespace boost
else
{
#if BOOST_PLAT_WINDOWS_RUNTIME
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
#else
::boost::detail::win32::Sleep(milliseconds);
#endif
}
}

#if BOOST_PLAT_WINDOWS_RUNTIME
class BOOST_THREAD_DECL scoped_winrt_thread
{
Expand Down Expand Up @@ -639,7 +639,7 @@ namespace boost
}
old=current;
}
while(true);
while(true) ;
return (old&value)!=0;
}

Expand All @@ -656,7 +656,7 @@ namespace boost
}
old=current;
}
while(true);
while(true) ;
return (old&value)!=0;
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/pthread/once.cpp
Expand Up @@ -15,7 +15,9 @@
#include <pthread.h>
#include <stdlib.h>
#include <memory>

#if defined BOOST_THREAD_PATCH
#include <string.h> // memcmp.
#endif
namespace boost
{
namespace thread_detail
Expand Down
13 changes: 7 additions & 6 deletions src/pthread/thread.cpp
Expand Up @@ -80,6 +80,8 @@ namespace boost
static void tls_destructor(void* data)
{
boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(data)->shared_from_this();

if(thread_info)
{
while(!thread_info->tss_data.empty() || thread_info->thread_exit_callbacks)
Expand Down Expand Up @@ -124,7 +126,8 @@ namespace boost
}
~delete_current_thread_tls_key_on_dlclose_t()
{
if (current_thread_tls_init_flag.epoch!=BOOST_ONCE_INITIAL_FLAG_VALUE)
const boost::once_flag uninitialized = BOOST_ONCE_INIT;
if (memcmp(&current_thread_tls_init_flag, &uninitialized, sizeof(boost::once_flag)))
{
pthread_key_delete(current_thread_tls_key);
}
Expand Down Expand Up @@ -158,8 +161,9 @@ namespace boost
{
static void* thread_proxy(void* param)
{
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
//thread_info->self.reset();
//boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->shared_from_this();
thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_TRY
Expand Down Expand Up @@ -252,7 +256,6 @@ namespace boost
{
thread_info->self.reset();
return false;
// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create"));
}
return true;
}
Expand All @@ -266,15 +269,13 @@ namespace boost
{
thread_info->self.reset();
return false;
// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_create"));
}
int detached_state;
res = pthread_attr_getdetachstate(h, &detached_state);
if (res != 0)
{
thread_info->self.reset();
return false;
// boost::throw_exception(thread_resource_error(res, "boost thread: failed in pthread_attr_getdetachstate"));
}
if (PTHREAD_CREATE_DETACHED==detached_state)
{
Expand Down
13 changes: 11 additions & 2 deletions test/Jamfile.v2
Expand Up @@ -298,6 +298,7 @@ rule thread-compile ( sources : reqs * : name )
[ thread-compile test_10963.cpp : : test_10963_c ]
[ thread-run test_10964.cpp ]
[ thread-test test_11053.cpp ]
[ thread-run test_11266.cpp ]
;


Expand Down Expand Up @@ -947,11 +948,19 @@ rule thread-compile ( sources : reqs * : name )
[ thread-run2-noit ./experimental/parallel/v2/task_region_pass.cpp : task_region_p ]
;

explicit ts_ ;
test-suite ts_
explicit ts_other ;
test-suite ts_other
:
[ thread-run2 ../example/this_executor.cpp : ex_this_executor ]
[ thread-run2 ../example/default_executor.cpp : ex_default_executor ]
;

explicit ts_ ;
test-suite ts_
:
#[ thread-run test_11256.cpp ]
[ thread-run test_11499.cpp ]
;


}
4 changes: 4 additions & 0 deletions test/sync/futures/future/then_deferred_pass.cpp
Expand Up @@ -17,6 +17,7 @@

#include <boost/thread/future.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>

#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION

Expand All @@ -31,6 +32,8 @@ int p1()

int p2(boost::future<int> f)
{
assert(f.is_ready());

BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
Expand All @@ -41,6 +44,7 @@ int p2(boost::future<int> f)

void p3(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
Expand Down
3 changes: 3 additions & 0 deletions test/sync/futures/future/then_executor_pass.cpp
Expand Up @@ -20,6 +20,7 @@
#include <boost/thread/executors/basic_thread_pool.hpp>
#include <boost/thread/executor.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <cassert>

#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION

Expand All @@ -34,6 +35,7 @@ int p1()

int p2(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p2 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
Expand All @@ -44,6 +46,7 @@ int p2(boost::future<int> f)

void p3(boost::future<int> f)
{
assert(f.is_ready());
BOOST_THREAD_LOG << "p3 <" << &f << BOOST_THREAD_END_LOG;
BOOST_TEST(f.valid());
int i = f.get();
Expand Down
Expand Up @@ -54,7 +54,7 @@ int main()
BOOST_TEST(i == 1);

}
catch(std::exception& ex)
catch(std::exception& )
{
BOOST_TEST(false);
}
Expand Down
Expand Up @@ -185,7 +185,7 @@ int main()
// empty queue try_push lvalue succeeds
boost::deque_adaptor<boost::sync_deque<int> > sq;
boost::deque_back<int> q(sq);
int i;
int i=0;
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
Expand Down
Expand Up @@ -74,7 +74,7 @@ void f()
}
{
time_point t0 = Clock::now();
while (true)
for (;;)
{
#if ! defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
auto
Expand Down
Expand Up @@ -185,7 +185,7 @@ int main()
// empty queue try_push lvalue succeeds
boost::queue_adaptor<boost::sync_queue<int> > sq;
boost::queue_back<int> q(sq);
int i;
int i=0;
BOOST_TEST(boost::queue_op_status::success == q.try_push(i));
BOOST_TEST(! q.empty());
BOOST_TEST(! q.full());
Expand Down
Expand Up @@ -29,7 +29,7 @@ int main()
boost::recursive_mutex::native_handle_type h = m.native_handle();
BOOST_TEST(h);
#else
#error "Test not applicable: BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE not defined for this platform as not supported"
#error "Test not applicable: BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE not defined for this platform as not supported"
#endif

return boost::report_errors();
Expand Down
4 changes: 2 additions & 2 deletions test/sync/mutual_exclusion/sync_pq/pq_multi_thread_pass.cpp
Expand Up @@ -105,7 +105,7 @@ void atomic_pull(sync_pq* q, boost::atomic<int>* sum)
const int val = q->pull();
sum->fetch_add(val);
}
catch(std::exception& e ){
catch(std::exception& ){
break;
}
}
Expand Down Expand Up @@ -147,7 +147,7 @@ void move_between_queues(sync_pq* q1, sync_pq* q2)
const int val = q1->pull();
q2->push(val);
}
catch(std::exception& e){
catch(std::exception& ){
break;
}
}
Expand Down
17 changes: 17 additions & 0 deletions test/test_10963.cpp
Expand Up @@ -8,9 +8,12 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_PROVIDES_EXECUTORS

#include <boost/thread/future.hpp>
#include <boost/static_assert.hpp>
#include <cassert>
#include <boost/thread/executors/basic_thread_pool.hpp>


struct TestCallback
Expand All @@ -19,12 +22,14 @@ struct TestCallback

result_type operator()(boost::future<void> future) const
{
assert(future.is_ready());
future.get();
return boost::make_ready_future();
}

result_type operator()(boost::future<boost::future<void> > future) const
{
assert(future.is_ready());
future.get();
return boost::make_ready_future();
}
Expand All @@ -33,12 +38,24 @@ struct TestCallback
int main()
{
#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
{
boost::promise<void> test_promise;
boost::future<void> test_future(test_promise.get_future());
auto f1 = test_future.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);
}
{
boost::basic_thread_pool executor;
boost::promise<void> test_promise;
boost::future<void> test_future(test_promise.get_future());
auto f1 = test_future.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<boost::future<void> > >::value);

}
#endif
return 0;
}
92 changes: 89 additions & 3 deletions test/test_10964.cpp
Expand Up @@ -8,23 +8,36 @@
#if ! defined BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif
#define BOOST_THREAD_PROVIDES_EXECUTORS

#include <boost/thread/future.hpp>
#include <boost/static_assert.hpp>
#include <cassert>
#include <boost/thread/executors/basic_thread_pool.hpp>

struct TestCallback
{
typedef boost::future<void> result_type;

result_type operator()(boost::future<void> future) const
{
future.get();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
future.wait();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
return boost::make_ready_future();
}

result_type operator()(boost::future<boost::future<void> > future) const
{
future.get();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
assert(future.get().is_ready());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
//boost::future<void> ff = future.get();

return boost::make_ready_future();
}
};
Expand All @@ -35,6 +48,9 @@ void p1()

int main()
{
const int number_of_tests = 2;
(void)(number_of_tests);

#if ! defined BOOST_NO_CXX11_DECLTYPE && ! defined BOOST_NO_CXX11_AUTO_DECLARATIONS
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
{
Expand All @@ -43,34 +59,104 @@ int main()
f1.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
auto f2 = f1.unwrap();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
f2.wait();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
boost::future<void> f2 = f1.get();
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::make_ready_future().then(
TestCallback()).unwrap().then(TestCallback()).get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::future<void> f = boost::async(p1);
f.then(
TestCallback()).unwrap().then(TestCallback()).get();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
auto f1 = boost::make_ready_future().then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f3 = f1.then(TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}


std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::basic_thread_pool executor;
auto f1 = boost::make_ready_future().then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f3 = f1.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::basic_thread_pool executor(1);

auto f1 = boost::make_ready_future().then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f1.valid()) << std::endl;
auto f2 = f1.unwrap();
std::cout << __FILE__ << "[" << __LINE__ << "] " << int(f2.valid()) << std::endl;

BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;
for (int i=0; i< number_of_tests; i++)
{
boost::basic_thread_pool executor;

auto f1 = boost::make_ready_future().then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f1), boost::future<boost::future<void> > >::value);
auto f2 = f1.unwrap();
BOOST_STATIC_ASSERT(std::is_same<decltype(f2), boost::future<void> >::value);
auto f3 = f2.then(executor, TestCallback());
BOOST_STATIC_ASSERT(std::is_same<decltype(f3), boost::future<boost::future<void> > >::value);
f3.wait();
}
std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl;

#endif
return 0;
}
42 changes: 42 additions & 0 deletions test/test_11256.cpp
@@ -0,0 +1,42 @@
// Copyright (C) 2015 Vicente Botet
//
// 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)

#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS

#include <boost/thread.hpp>
#include <boost/thread/thread_pool.hpp>
#include <cassert>

auto createFuture()
{
boost::promise<void> promise;
promise.set_value();
return promise.get_future();
}

auto stepOne(boost::basic_thread_pool &executor)
{
auto sendFuture = createFuture();
auto wrappedFuture = sendFuture.then(executor, [](auto f) mutable {
return createFuture();
});

return wrappedFuture.unwrap();
}

auto stepTwo(boost::basic_thread_pool &executor)
{
auto future = stepOne(executor);
return future.then(executor, [](auto f) {
assert(f.is_ready());
});
}

int main()
{
boost::basic_thread_pool executor{1};
stepTwo(executor).get();
}
29 changes: 29 additions & 0 deletions test/test_11266.cpp
@@ -0,0 +1,29 @@
// Copyright (C) 2015 Vicente Botet
//
// 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)

#define BOOST_THREAD_VERSION 4

#include <boost/thread/future.hpp>

void func(int) { }

int main()
{
#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
{
boost::packaged_task<void(int)> task{func};
}
{
boost::packaged_task<void(int)> task{func};

task(0);
}
{
boost::packaged_task<void(int)> task{func};
int x = 0;
task(x);
}
#endif
}
56 changes: 56 additions & 0 deletions test/test_11499.cpp
@@ -0,0 +1,56 @@
// Copyright (C) 2014 Vicente Botet
//
// 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)

#define BOOST_THREAD_VERSION 4

#include <boost/thread/shared_mutex.hpp>
#include <thread>
#include <mutex>
#include <shared_mutex>
#include <atomic>
#include <vector>

using MutexT = boost::shared_mutex;
using ReaderLockT = std::lock_guard<MutexT>;
using WriterLockT = std::shared_lock<MutexT>;

MutexT gMutex;
std::atomic<bool> running(true);


void myread()
{
long reads = 0;
while (running && reads < 100000)
{
ReaderLockT lock(gMutex);
std::this_thread::yield();
++reads;
}
}

int main()
{
using namespace std;

vector<thread> threads;
for (int i = 0; i < 256; ++i)
{
threads.emplace_back(thread(myread));
}

// string str;
//
// getline(std::cin, str);
running = false;

for (auto& thread : threads)
{
thread.join();
}

return 0;
}

2 changes: 2 additions & 0 deletions test/test_2741.cpp
Expand Up @@ -35,6 +35,7 @@ BOOST_AUTO_TEST_CASE(test_native_handle)
boost::thread_attributes attrs;

boost::thread_attributes::native_handle_type* h = attrs.native_handle();
(void)(h); // unused
#if defined(BOOST_THREAD_PLATFORM_WIN32)
// ... window version
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
Expand Down Expand Up @@ -75,3 +76,4 @@ BOOST_AUTO_TEST_CASE(test_creation_with_attrs)
timed_test(&do_test_creation_with_attrs, 1);
}


2 changes: 1 addition & 1 deletion test/test_4648.cpp
Expand Up @@ -30,7 +30,7 @@ int boostThreadLocksTest::firstFunction(boostThreadLocksTest *pBoostThreadLocksT
std::cout<<"Returning from "<<boost::this_thread::get_id()<<" "<<"firstFunction"<<std::endl;
return(0);
}
int boostThreadLocksTest::secondFunction(boostThreadLocksTest */*pBoostThreadLocksTest*/, boost::upgrade_lock<boost::shared_mutex>& upgr) {
int boostThreadLocksTest::secondFunction(boostThreadLocksTest *, boost::upgrade_lock<boost::shared_mutex>& upgr) {
std::cout<<"Before Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl;
boost::upgrade_to_unique_lock<boost::shared_mutex> localUniqueLock(upgr);
std::cout<<"After Exclusive Locking "<<boost::this_thread::get_id()<<" "<<"secondFunction"<<std::endl;
Expand Down
2 changes: 1 addition & 1 deletion test/test_4882.cpp
Expand Up @@ -45,7 +45,7 @@ void thread()
#endif
}
}
BOOST_CATCH (boost::lock_error& le)
BOOST_CATCH (boost::lock_error& )
{
//BOOST_THREAD_LOG << "lock_error exception thrd>" << BOOST_THREAD_END_LOG;
}
Expand Down
8 changes: 4 additions & 4 deletions test/threads/this_thread/sleep_until/sleep_until_pass.cpp
Expand Up @@ -28,7 +28,7 @@ int main()
{
typedef boost::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::sleep_until(t0 + ms);
Expand All @@ -43,7 +43,7 @@ int main()
{
typedef boost::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::sleep_until(t0 + ms);
Expand All @@ -58,7 +58,7 @@ int main()
{
typedef boost::chrono::steady_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::no_interruption_point::sleep_until(t0 + ms);
Expand All @@ -73,7 +73,7 @@ int main()
{
typedef boost::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
//typedef Clock::duration duration;
boost::chrono::milliseconds ms(500);
time_point t0 = Clock::now();
boost::this_thread::no_interruption_point::sleep_until(t0 + ms);
Expand Down
8 changes: 4 additions & 4 deletions test/threads/thread/constr/FArgs_pass.cpp
Expand Up @@ -26,9 +26,9 @@
unsigned throw_one = 0xFFFF;

#if defined _GLIBCXX_THROW
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
inline void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
#elif defined BOOST_MSVC
void* operator new(std::size_t s)
inline void* operator new(std::size_t s)
#else
void* operator new(std::size_t s) throw (std::bad_alloc)
#endif
Expand All @@ -40,9 +40,9 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
}

#if defined BOOST_MSVC
void operator delete(void* p)
inline void operator delete(void* p)
#else
void operator delete(void* p) throw ()
inline void operator delete(void* p) throw ()
#endif
{
std::cout << __FILE__ << ":" << __LINE__ << std::endl;
Expand Down
8 changes: 4 additions & 4 deletions test/threads/thread/constr/lambda_pass.cpp
Expand Up @@ -28,9 +28,9 @@
unsigned throw_one = 0xFFFF;

#if defined _GLIBCXX_THROW
void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
inline void* operator new(std::size_t s) _GLIBCXX_THROW (std::bad_alloc)
#elif defined BOOST_MSVC
void* operator new(std::size_t s)
inline void* operator new(std::size_t s)
#else
void* operator new(std::size_t s) throw (std::bad_alloc)
#endif
Expand All @@ -41,9 +41,9 @@ void* operator new(std::size_t s) throw (std::bad_alloc)
}

#if defined BOOST_MSVC
void operator delete(void* p)
inline void operator delete(void* p)
#else
void operator delete(void* p) throw ()
inline void operator delete(void* p) throw ()
#endif
{
std::free(p);
Expand Down