diff --git a/doc/acknowledgements.xml b/doc/acknowledgements.xml index 6e8c610a..60ad9198 100644 --- a/doc/acknowledgements.xml +++ b/doc/acknowledgements.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/barrier-ref.xml b/doc/barrier-ref.xml index 5f4073f9..10b5519b 100644 --- a/doc/barrier-ref.xml +++ b/doc/barrier-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/bibliography.xml b/doc/bibliography.xml index e604f384..458d6392 100644 --- a/doc/bibliography.xml +++ b/doc/bibliography.xml @@ -6,7 +6,7 @@ ]> diff --git a/doc/build.xml b/doc/build.xml index bed1c7a7..7f426771 100644 --- a/doc/build.xml +++ b/doc/build.xml @@ -7,7 +7,7 @@
Build diff --git a/doc/concepts.xml b/doc/concepts.xml index 2004236c..30386f70 100644 --- a/doc/concepts.xml +++ b/doc/concepts.xml @@ -6,7 +6,7 @@ ]>
Concepts diff --git a/doc/condition-ref.xml b/doc/condition-ref.xml index b5882d27..51b3b1d0 100644 --- a/doc/condition-ref.xml +++ b/doc/condition-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/configuration.xml b/doc/configuration.xml index e54542a4..bb42d665 100644 --- a/doc/configuration.xml +++ b/doc/configuration.xml @@ -6,7 +6,7 @@ ]>
Configuration diff --git a/doc/design.xml b/doc/design.xml index b1d4d51a..c9b58480 100644 --- a/doc/design.xml +++ b/doc/design.xml @@ -6,7 +6,7 @@ ]>
Design diff --git a/doc/entities.xml b/doc/entities.xml index a056e193..fbfa6d21 100644 --- a/doc/entities.xml +++ b/doc/entities.xml @@ -1,6 +1,6 @@ Boost"> Boost.Thread"> diff --git a/doc/exceptions-ref.xml b/doc/exceptions-ref.xml index 4af5bd9b..0ae42e8b 100644 --- a/doc/exceptions-ref.xml +++ b/doc/exceptions-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/faq.xml b/doc/faq.xml index 96c828b9..482d6811 100644 --- a/doc/faq.xml +++ b/doc/faq.xml @@ -6,7 +6,7 @@ ]>
Frequently Asked Questions diff --git a/doc/glossary.xml b/doc/glossary.xml index 26ead3c4..ad1c8442 100644 --- a/doc/glossary.xml +++ b/doc/glossary.xml @@ -6,7 +6,7 @@ ]> Glossary diff --git a/doc/implementation_notes.xml b/doc/implementation_notes.xml index 03377461..c097b070 100644 --- a/doc/implementation_notes.xml +++ b/doc/implementation_notes.xml @@ -6,7 +6,7 @@ ]>
Implementation Notes diff --git a/doc/index.html b/doc/index.html index 94d75801..4d1b5db3 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,6 +1,6 @@ diff --git a/doc/mutex-ref.xml b/doc/mutex-ref.xml index 34d8b17e..5faa2630 100644 --- a/doc/mutex-ref.xml +++ b/doc/mutex-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/once-ref.xml b/doc/once-ref.xml index 12480f57..d6520178 100644 --- a/doc/once-ref.xml +++ b/doc/once-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/overview.xml b/doc/overview.xml index 545bf1a5..1e639597 100644 --- a/doc/overview.xml +++ b/doc/overview.xml @@ -6,7 +6,7 @@ ]>
Overview diff --git a/doc/rationale.xml b/doc/rationale.xml index 8a77d99b..aeaf8511 100644 --- a/doc/rationale.xml +++ b/doc/rationale.xml @@ -6,7 +6,7 @@ ]>
Rationale diff --git a/doc/read_write_mutex-ref.xml b/doc/read_write_mutex-ref.xml index 46336961..747960fb 100644 --- a/doc/read_write_mutex-ref.xml +++ b/doc/read_write_mutex-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/recursive_mutex-ref.xml b/doc/recursive_mutex-ref.xml index 9a9d36d2..de95494a 100644 --- a/doc/recursive_mutex-ref.xml +++ b/doc/recursive_mutex-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/reference.xml b/doc/reference.xml index a9167d02..d6ea4d75 100644 --- a/doc/reference.xml +++ b/doc/reference.xml @@ -6,7 +6,7 @@ ]>
Release Notes diff --git a/doc/thread-ref.xml b/doc/thread-ref.xml index ad33271b..270302ca 100644 --- a/doc/thread-ref.xml +++ b/doc/thread-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/thread.xml b/doc/thread.xml index 209f48f9..f5c30883 100644 --- a/doc/thread.xml +++ b/doc/thread.xml @@ -6,7 +6,7 @@ ]> Subject to the Boost Software License, Version 1.0. - (See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) + (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) Portable C++ multi-threading diff --git a/doc/tss-ref.xml b/doc/tss-ref.xml index 54399d4c..faacad1f 100644 --- a/doc/tss-ref.xml +++ b/doc/tss-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/doc/xtime-ref.xml b/doc/xtime-ref.xml index de7fd999..566a28d1 100644 --- a/doc/xtime-ref.xml +++ b/doc/xtime-ref.xml @@ -6,7 +6,7 @@ ]>
diff --git a/include/boost/thread/pthread/thread.hpp b/include/boost/thread/pthread/thread.hpp index 24437ba6..f539d568 100644 --- a/include/boost/thread/pthread/thread.hpp +++ b/include/boost/thread/pthread/thread.hpp @@ -21,6 +21,7 @@ #include #include #include "thread_data.hpp" +#include namespace boost { @@ -133,6 +134,12 @@ namespace boost explicit thread(detail::thread_data_ptr data); detail::thread_data_ptr get_thread_info() const; + + template + static inline detail::thread_data_ptr make_thread_info(F f) + { + return detail::thread_data_ptr(new thread_data(f)); + } public: thread(); @@ -140,13 +147,32 @@ namespace boost template explicit thread(F f): - thread_info(new thread_data(f)) + thread_info(make_thread_info(f)) { start_thread(); } template thread(detail::thread_move_t f): - thread_info(new thread_data(f)) + thread_info(make_thread_info(f)) + { + start_thread(); + } + + template + thread(F f,A1 a1): + thread_info(make_thread_info(boost::bind(f,a1))) + { + start_thread(); + } + template + thread(F f,A1 a1,A2 a2): + thread_info(make_thread_info(boost::bind(f,a1,a2))) + { + start_thread(); + } + template + thread(F f,A1 a1,A2 a2,A3 a3): + thread_info(make_thread_info(boost::bind(f,a1,a2,a3))) { start_thread(); } diff --git a/include/boost/thread/pthread/tss.hpp b/include/boost/thread/pthread/tss.hpp index 36c385c5..626f1c30 100644 --- a/include/boost/thread/pthread/tss.hpp +++ b/include/boost/thread/pthread/tss.hpp @@ -52,7 +52,7 @@ namespace boost void operator()(void* data) { - cleanup_function(data); + cleanup_function(static_cast(data)); } }; diff --git a/include/boost/thread/win32/basic_recursive_mutex.hpp b/include/boost/thread/win32/basic_recursive_mutex.hpp index e5f79981..d2b8e77d 100644 --- a/include/boost/thread/win32/basic_recursive_mutex.hpp +++ b/include/boost/thread/win32/basic_recursive_mutex.hpp @@ -56,6 +56,12 @@ namespace boost long const current_thread_id=win32::GetCurrentThreadId(); return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target); } + template + bool timed_lock(Duration const& timeout) + { + return timed_lock(get_system_time()+timeout); + } + long get_active_count() { return mutex.get_active_count(); diff --git a/include/boost/thread/win32/basic_timed_mutex.hpp b/include/boost/thread/win32/basic_timed_mutex.hpp index fef19d7b..8ee199df 100644 --- a/include/boost/thread/win32/basic_timed_mutex.hpp +++ b/include/boost/thread/win32/basic_timed_mutex.hpp @@ -104,6 +104,12 @@ namespace boost return true; } + template + bool timed_lock(Duration const& timeout) + { + return timed_lock(get_system_time()+timeout); + } + long get_active_count() { return ::boost::detail::interlocked_read_acquire(&active_count); diff --git a/include/boost/thread/win32/once.hpp b/include/boost/thread/win32/once.hpp index d1a525de..b11be97a 100644 --- a/include/boost/thread/win32/once.hpp +++ b/include/boost/thread/win32/once.hpp @@ -94,9 +94,9 @@ namespace boost detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); #ifdef BOOST_NO_ANSI_APIS - return win32::CreateMutexW(NULL, 0, mutex_name); + return win32::CreateMutexW(0, 0, mutex_name); #else - return win32::CreateMutexA(NULL, 0, mutex_name); + return win32::CreateMutexA(0, 0, mutex_name); #endif } diff --git a/include/boost/thread/win32/shared_mutex.hpp b/include/boost/thread/win32/shared_mutex.hpp index 73cdc490..3b322b1f 100644 --- a/include/boost/thread/win32/shared_mutex.hpp +++ b/include/boost/thread/win32/shared_mutex.hpp @@ -57,12 +57,12 @@ namespace boost { if(old_state.exclusive_waiting) { - BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=0); + BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0); } if(old_state.shared_waiting || old_state.exclusive_waiting) { - BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),NULL)!=0); + BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); } } @@ -215,7 +215,7 @@ namespace boost { if(old_state.upgrade) { - BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,NULL)!=0); + BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0); } else { diff --git a/include/boost/thread/win32/thread.hpp b/include/boost/thread/win32/thread.hpp index 9ff339ec..61c2908a 100644 --- a/include/boost/thread/win32/thread.hpp +++ b/include/boost/thread/win32/thread.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace boost { @@ -189,19 +190,44 @@ namespace boost explicit thread(detail::thread_data_ptr data); detail::thread_data_ptr get_thread_info() const; + + template + static inline detail::thread_data_ptr make_thread_info(F f) + { + return detail::heap_new >(f); + } public: thread(); ~thread(); template explicit thread(F f): - thread_info(detail::heap_new >(f)) + thread_info(make_thread_info(f)) { start_thread(); } template thread(detail::thread_move_t f): - thread_info(detail::heap_new >(f)) + thread_info(make_thread_info(f)) + { + start_thread(); + } + + template + thread(F f,A1 a1): + thread_info(make_thread_info(boost::bind(f,a1))) + { + start_thread(); + } + template + thread(F f,A1 a1,A2 a2): + thread_info(make_thread_info(boost::bind(f,a1,a2))) + { + start_thread(); + } + template + thread(F f,A1 a1,A2 a2,A3 a3): + thread_info(make_thread_info(boost::bind(f,a1,a2,a3))) { start_thread(); } diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index c8d55d29..f8f66b15 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -181,9 +181,9 @@ namespace boost inline handle create_anonymous_semaphore(long initial_count,long max_count) { #if !defined(BOOST_NO_ANSI_APIS) - handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL); + handle const res=CreateSemaphoreA(0,initial_count,max_count,0); #else - handle const res=CreateSemaphoreW(NULL,initial_count,max_count,NULL); + handle const res=CreateSemaphoreW(0,initial_count,max_count,0); #endif if(!res) { diff --git a/include/boost/thread/win32/tss.hpp b/include/boost/thread/win32/tss.hpp index fcf792bd..91870f14 100644 --- a/include/boost/thread/win32/tss.hpp +++ b/include/boost/thread/win32/tss.hpp @@ -51,7 +51,7 @@ namespace boost void operator()(void* data) { - cleanup_function(data); + cleanup_function(static_cast(data)); } }; diff --git a/index.html b/index.html index 1bc26cab..f54e21e2 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ diff --git a/src/tss_null.cpp b/src/tss_null.cpp index 3288c679..ff13b30f 100644 --- a/src/tss_null.cpp +++ b/src/tss_null.cpp @@ -6,7 +6,7 @@ #include -#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST)) && (!defined(_MSC_VER) || defined(UNDER_CE)) +#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE)) /* This file is a "null" implementation of tss cleanup; it's diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d9e4bcb9..0145cf5b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,6 +38,7 @@ rule thread-run ( sources ) [ thread-run test_thread_id.cpp ] [ thread-run test_hardware_concurrency.cpp ] [ thread-run test_thread_move.cpp ] + [ thread-run test_thread_launching.cpp ] [ thread-run test_move_function.cpp ] [ thread-run test_mutex.cpp ] [ thread-run test_condition_notify_one.cpp ] diff --git a/test/test_mutex.cpp b/test/test_mutex.cpp index 5dae38ee..e85459c4 100644 --- a/test/test_mutex.cpp +++ b/test/test_mutex.cpp @@ -150,6 +150,17 @@ struct test_timedlock boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100); BOOST_CHECK(lock.timed_lock(target)); BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + + BOOST_CHECK(mutex.timed_lock(boost::posix_time::milliseconds(100))); + mutex.unlock(); + + BOOST_CHECK(lock.timed_lock(boost::posix_time::milliseconds(100))); + BOOST_CHECK(lock ? true : false); + lock.unlock(); + BOOST_CHECK(!lock); + } }; diff --git a/test/test_thread_launching.cpp b/test/test_thread_launching.cpp new file mode 100644 index 00000000..28903dbc --- /dev/null +++ b/test/test_thread_launching.cpp @@ -0,0 +1,164 @@ +// Copyright (C) 2007 Anthony Williams +// +// 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) +#include +#include +#include +#include +#include +#include + +bool normal_function_called=false; + +void normal_function() +{ + normal_function_called=true; +} + +void test_thread_function_no_arguments() +{ + boost::thread function(normal_function); + function.join(); + BOOST_CHECK(normal_function_called); +} + +struct callable_no_args +{ + static bool called; + + void operator()() const + { + called=true; + } +}; + +bool callable_no_args::called=false; + +void test_thread_callable_object_no_arguments() +{ + boost::thread callable((callable_no_args())); + callable.join(); + BOOST_CHECK(callable_no_args::called); +} + +struct callable_noncopyable_no_args: + boost::noncopyable +{ + static bool called; + + void operator()() const + { + called=true; + } +}; + +bool callable_noncopyable_no_args::called=false; + +void test_thread_callable_object_ref_no_arguments() +{ + callable_noncopyable_no_args func; + + boost::thread callable(boost::ref(func)); + callable.join(); + BOOST_CHECK(callable_noncopyable_no_args::called); +} + +struct callable_one_arg +{ + static bool called; + static int called_arg; + + void operator()(int arg) const + { + called=true; + called_arg=arg; + } +}; + +bool callable_one_arg::called=false; +int callable_one_arg::called_arg=0; + +void test_thread_callable_object_one_argument() +{ + boost::thread callable(callable_one_arg(),42); + callable.join(); + BOOST_CHECK(callable_one_arg::called); + BOOST_CHECK_EQUAL(callable_one_arg::called_arg,42); +} + +struct callable_multiple_arg +{ + static bool called_two; + static int called_two_arg1; + static double called_two_arg2; + static bool called_three; + static std::string called_three_arg1; + static std::vector called_three_arg2; + static int called_three_arg3; + + void operator()(int arg1,double arg2) const + { + called_two=true; + called_two_arg1=arg1; + called_two_arg2=arg2; + } + void operator()(std::string const& arg1,std::vector const& arg2,int arg3) const + { + called_three=true; + called_three_arg1=arg1; + called_three_arg2=arg2; + called_three_arg3=arg3; + } +}; + +bool callable_multiple_arg::called_two=false; +bool callable_multiple_arg::called_three=false; +int callable_multiple_arg::called_two_arg1; +double callable_multiple_arg::called_two_arg2; +std::string callable_multiple_arg::called_three_arg1; +std::vector callable_multiple_arg::called_three_arg2; +int callable_multiple_arg::called_three_arg3; + +void test_thread_callable_object_multiple_arguments() +{ + std::vector x; + for(unsigned i=0;i<7;++i) + { + x.push_back(i*i); + } + + boost::thread callable3(callable_multiple_arg(),"hello",x,1.2); + callable3.join(); + BOOST_CHECK(callable_multiple_arg::called_three); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg1,"hello"); + BOOST_CHECK_EQUAL(callable_multiple_arg::called_three_arg2.size(),x.size()); + for(unsigned j=0;jadd(BOOST_TEST_CASE(test_thread_function_no_arguments)); + test->add(BOOST_TEST_CASE(test_thread_callable_object_no_arguments)); + test->add(BOOST_TEST_CASE(test_thread_callable_object_ref_no_arguments)); + test->add(BOOST_TEST_CASE(test_thread_callable_object_one_argument)); + test->add(BOOST_TEST_CASE(test_thread_callable_object_multiple_arguments)); + return test; +} diff --git a/test/test_tss.cpp b/test/test_tss.cpp index 462c5523..8c46d3db 100644 --- a/test/test_tss.cpp +++ b/test/test_tss.cpp @@ -187,12 +187,54 @@ void test_tss() timed_test(&do_test_tss, 2); } +bool tss_cleanup_called=false; + +struct Dummy +{}; + +void tss_custom_cleanup(Dummy* d) +{ + delete d; + tss_cleanup_called=true; +} + +boost::thread_specific_ptr tss_with_cleanup(tss_custom_cleanup); + +void tss_thread_with_custom_cleanup() +{ + tss_with_cleanup.reset(new Dummy); +} + +void do_test_tss_with_custom_cleanup() +{ + boost::thread t(tss_thread_with_custom_cleanup); + try + { + t.join(); + } + catch(...) + { + t.interrupt(); + t.join(); + throw; + } + + BOOST_CHECK(tss_cleanup_called); +} + + +void test_tss_with_custom_cleanup() +{ + timed_test(&do_test_tss_with_custom_cleanup, 2); +} + boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) { boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Threads: tss test suite"); test->add(BOOST_TEST_CASE(test_tss)); + test->add(BOOST_TEST_CASE(test_tss_with_custom_cleanup)); return test; }