From aa6dd59f3b6e689c5d4714bf199f7ab1dffe3780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Mon, 16 Sep 2013 17:01:45 +0000 Subject: [PATCH] Last merge for 1.55 (Interprocess) [SVN r85705] --- example/Jamfile.v2 | 4 +- .../detail/os_thread_functions.hpp | 104 +++++++++++- .../boost/interprocess/detail/workaround.hpp | 21 ++- proj/vc7ide/interprocesslib.vcproj | 3 + test/Jamfile.v2 | 2 +- test/boost_interprocess_check.hpp | 2 +- test/condition_test_template.hpp | 157 ++++++++---------- test/message_queue_test.cpp | 9 +- test/mutex_test_template.hpp | 128 +++++++------- test/named_creation_template.hpp | 8 +- test/named_semaphore_test.cpp | 12 +- test/sharable_mutex_test_template.hpp | 125 ++++++++------ test/util.hpp | 24 +-- 13 files changed, 356 insertions(+), 243 deletions(-) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 286b45a..34cce67 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -21,7 +21,7 @@ rule test_all for local fileb in [ glob comp*.cpp ] { - all_rules += [ link $(fileb) /boost/thread//boost_thread + all_rules += [ link $(fileb) : # additional args acc:-lrt acc-pa_risc:-lrt @@ -35,7 +35,7 @@ rule test_all for local fileb in [ glob doc_*.cpp ] { - all_rules += [ run $(fileb) /boost/thread//boost_thread + all_rules += [ run $(fileb) : # additional args : # test-files : # requirements diff --git a/include/boost/interprocess/detail/os_thread_functions.hpp b/include/boost/interprocess/detail/os_thread_functions.hpp index cc4149c..c634800 100644 --- a/include/boost/interprocess/detail/os_thread_functions.hpp +++ b/include/boost/interprocess/detail/os_thread_functions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2013. 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) // @@ -8,6 +8,17 @@ // ////////////////////////////////////////////////////////////////////////////// +//Thread launching functions are adapted from boost/detail/lightweight_thread.hpp +// +// boost/detail/lightweight_thread.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 Peter Dimov +// +// 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 + #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP @@ -16,9 +27,11 @@ #include #include #include +#include #if defined(BOOST_INTERPROCESS_WINDOWS) # include +# include #else # include # include @@ -56,6 +69,7 @@ namespace ipcdetail{ typedef unsigned long OS_process_id_t; typedef unsigned long OS_thread_id_t; +typedef void* OS_thread_t; typedef OS_thread_id_t OS_systemwide_thread_id_t; //process @@ -198,6 +212,7 @@ inline unsigned int get_num_cores() #else //#if (defined BOOST_INTERPROCESS_WINDOWS) +typedef pthread_t OS_thread_t; typedef pthread_t OS_thread_id_t; typedef pid_t OS_process_id_t; @@ -446,6 +461,12 @@ inline unsigned int get_num_cores() #endif } +inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg) +{ return pthread_create(thread, 0, start_routine, arg); } + +inline void thread_join(OS_thread_t thread) +{ (void)pthread_join(thread, 0); } + #endif //#if (defined BOOST_INTERPROCESS_WINDOWS) typedef char pid_str_t[sizeof(OS_process_id_t)*3+1]; @@ -459,6 +480,87 @@ inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid) inline void get_pid_str(pid_str_t &pid_str) { get_pid_str(pid_str, get_current_process_id()); } +#if defined(BOOST_INTERPROCESS_WINDOWS) + +inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg ) +{ + void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); + + if( h != 0 ){ + *thread = h; + return 0; + } + else{ + return EAGAIN; + } +} + +inline void thread_join( OS_thread_t thread) +{ + winapi::wait_for_single_object( thread, winapi::infinite_time ); + winapi::close_handle( thread ); +} + +#endif + +class abstract_thread +{ + public: + virtual ~abstract_thread() {} + virtual void run() = 0; +}; + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +inline unsigned __stdcall launch_thread_routine( void * pv ) +{ + std::auto_ptr pt( static_cast( pv ) ); + pt->run(); + return 0; +} + +#else + +extern "C" void * launch_thread_routine( void * pv ); + +inline void * launch_thread_routine( void * pv ) +{ + std::auto_ptr pt( static_cast( pv ) ); + pt->run(); + return 0; +} + +#endif + +template +class launch_thread_impl + : public abstract_thread +{ + public: + explicit launch_thread_impl( F f ) + : f_( f ) + {} + + void run() + { f_(); } + + private: + F f_; +}; + +template +inline int thread_launch( OS_thread_t & pt, F f ) +{ + std::auto_ptr p( new launch_thread_impl( f ) ); + + int r = thread_create(&pt, launch_thread_routine, p.get()); + if( r == 0 ){ + p.release(); + } + + return r; +} + } //namespace ipcdetail{ } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/detail/workaround.hpp b/include/boost/interprocess/detail/workaround.hpp index 2ffe812..6ce2ea1 100644 --- a/include/boost/interprocess/detail/workaround.hpp +++ b/include/boost/interprocess/detail/workaround.hpp @@ -24,8 +24,25 @@ #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0) //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it. - //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seem to work. - #if !defined(__CYGWIN__) && !defined(__APPLE__) + #if defined(__CYGWIN__) + #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + //Mac Os X < Lion (10.7) might define _POSIX_THREAD_PROCESS_SHARED but there is no real support. + #elif defined(__APPLE__) + #include "TargetConditionals.h" + //Check we're on Mac OS target + #if defined(TARGET_OS_MAC) + #include "AvailabilityMacros.h" + //If minimum target for this compilation is older than Mac Os Lion, then we are out of luck + #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 + #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + #endif + #endif + #endif + + //If buggy _POSIX_THREAD_PROCESS_SHARED is detected avoid using it + #if defined(BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED) + #undef BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + #else #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED #endif #endif diff --git a/proj/vc7ide/interprocesslib.vcproj b/proj/vc7ide/interprocesslib.vcproj index 77aaba6..fa6e553 100644 --- a/proj/vc7ide/interprocesslib.vcproj +++ b/proj/vc7ide/interprocesslib.vcproj @@ -297,6 +297,9 @@ + + #include +#include #include "boost_interprocess_check.hpp" -#include #include -#include #include -#include -#include #include namespace boost{ @@ -41,31 +38,6 @@ boost::posix_time::ptime ptime_delay(int secs) boost::posix_time::time_duration(0, 0, secs); } -inline boost::xtime delay(int secs, int msecs=0, int nsecs=0) -{ - const int MILLISECONDS_PER_SECOND = 1000; - const int NANOSECONDS_PER_SECOND = 1000000000; - const int NANOSECONDS_PER_MILLISECOND = 1000000; - - boost::xtime xt; - - #if BOOST_VERSION >= 105100 //TIME_UTC is a macro in C11, breaking change in Boost.Thread - int ret = boost::xtime_get(&xt, boost::TIME_UTC_); - BOOST_INTERPROCES_CHECK(ret == static_cast(boost::TIME_UTC_));(void)ret; - #else - int ret = boost::xtime_get(&xt, boost::TIME_UTC); - BOOST_INTERPROCES_CHECK(ret == static_cast(boost::TIME_UTC));(void)ret; - #endif - nsecs += xt.nsec; - msecs += nsecs / NANOSECONDS_PER_MILLISECOND; - secs += msecs / MILLISECONDS_PER_SECOND; - nsecs += (msecs % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND; - xt.nsec = nsecs % NANOSECONDS_PER_SECOND; - xt.sec += secs + (nsecs / NANOSECONDS_PER_SECOND); - - return xt; -} - template class binder { @@ -104,10 +76,10 @@ void condition_test_thread(condition_test_data* data) { boost::interprocess::scoped_lock lock(data->mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); while (!(data->notified > 0)) data->condition.wait(lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); data->awoken++; } @@ -126,38 +98,38 @@ void condition_test_waits(condition_test_data* data) { boost::interprocess::scoped_lock lock(data->mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); // Test wait. while (data->notified != 1) data->condition.wait(lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data->notified == 1); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data->notified == 1); data->awoken++; data->condition.notify_one(); // Test predicate wait. data->condition.wait(lock, cond_predicate(data->notified, 2)); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data->notified == 2); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data->notified == 2); data->awoken++; data->condition.notify_one(); // Test timed_wait. while (data->notified != 3) data->condition.timed_wait(lock, ptime_delay(5)); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data->notified == 3); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data->notified == 3); data->awoken++; data->condition.notify_one(); // Test predicate timed_wait. cond_predicate pred(data->notified, 4); bool ret = data->condition.timed_wait(lock, ptime_delay(5), pred); - BOOST_INTERPROCES_CHECK(ret);(void)ret; - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(pred()); - BOOST_INTERPROCES_CHECK(data->notified == 4); + BOOST_INTERPROCESS_CHECK(ret);(void)ret; + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(pred()); + BOOST_INTERPROCESS_CHECK(data->notified == 4); data->awoken++; data->condition.notify_one(); } @@ -167,92 +139,97 @@ void do_test_condition_notify_one() { condition_test_data data; - boost::thread thread(bind_function(&condition_test_thread, &data)); + boost::interprocess::ipcdetail::OS_thread_t thread; + boost::interprocess::ipcdetail::thread_launch(thread, bind_function(&condition_test_thread, &data)); //Make sure thread is blocked - boost::thread::sleep(delay(1)); + boost::interprocess::ipcdetail::thread_sleep(1000); { boost::interprocess::scoped_lock lock(data.mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); data.notified++; data.condition.notify_one(); } - thread.join(); - BOOST_INTERPROCES_CHECK(data.awoken == 1); + boost::interprocess::ipcdetail::thread_join(thread); + BOOST_INTERPROCESS_CHECK(data.awoken == 1); } template void do_test_condition_notify_all() { const int NUMTHREADS = 3; - boost::thread_group threads; + + boost::interprocess::ipcdetail::OS_thread_t thgroup[NUMTHREADS]; condition_test_data data; - for (int i = 0; i < NUMTHREADS; ++i){ - threads.create_thread(bind_function(&condition_test_thread, &data)); + for(int i = 0; i< NUMTHREADS; ++i){ + boost::interprocess::ipcdetail::thread_launch(thgroup[i], bind_function(&condition_test_thread, &data)); } + //Make sure all threads are blocked - boost::thread::sleep(delay(1)); + boost::interprocess::ipcdetail::thread_sleep(1000); { boost::interprocess::scoped_lock lock(data.mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); data.notified++; } data.condition.notify_all(); - threads.join_all(); - BOOST_INTERPROCES_CHECK(data.awoken == NUMTHREADS); + for(int i = 0; i< NUMTHREADS; ++i){ + boost::interprocess::ipcdetail::thread_join(thgroup[i]); + } + BOOST_INTERPROCESS_CHECK(data.awoken == NUMTHREADS); } template void do_test_condition_waits() { condition_test_data data; - - boost::thread thread(bind_function(&condition_test_waits, &data)); + boost::interprocess::ipcdetail::OS_thread_t thread; + boost::interprocess::ipcdetail::thread_launch(thread, bind_function(&condition_test_waits, &data)); { boost::interprocess::scoped_lock lock(data.mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); - boost::thread::sleep(delay(1)); + boost::interprocess::ipcdetail::thread_sleep(1000); data.notified++; data.condition.notify_one(); while (data.awoken != 1) data.condition.wait(lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data.awoken == 1); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 1); - boost::thread::sleep(delay(1)); + boost::interprocess::ipcdetail::thread_sleep(1000); data.notified++; data.condition.notify_one(); while (data.awoken != 2) data.condition.wait(lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data.awoken == 2); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 2); - boost::thread::sleep(delay(1)); + boost::interprocess::ipcdetail::thread_sleep(1000); data.notified++; data.condition.notify_one(); while (data.awoken != 3) data.condition.wait(lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data.awoken == 3); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 3); - boost::thread::sleep(delay(1)); + boost::interprocess::ipcdetail::thread_sleep(1000); data.notified++; data.condition.notify_one(); while (data.awoken != 4) data.condition.wait(lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); - BOOST_INTERPROCES_CHECK(data.awoken == 4); + BOOST_INTERPROCESS_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(data.awoken == 4); } - thread.join(); - BOOST_INTERPROCES_CHECK(data.awoken == 4); + boost::interprocess::ipcdetail::thread_join(thread); + BOOST_INTERPROCESS_CHECK(data.awoken == 4); } /* //Message queue simulation test @@ -326,16 +303,15 @@ void do_test_condition_queue_notify_one(void) waiting_readers = 0; waiting_writer = 0; - boost::thread_group thgroup; - int i; - for(i = 0; i< NumThreads; ++i){ + boost::interprocess::ipcdetail::OS_thread_t thgroup[NumThreads]; + for(int i = 0; i< NumThreads; ++i){ condition_func func(cond_full, cond_empty, mutex); - thgroup.create_thread(func); + boost::interprocess::ipcdetail::thread_launch(thgroup[i], func); } //Add 20 elements one by one in the queue simulation //The sender will block if it fills the queue - for(i = 0; i < NumThreads; ++i){ + for(int i = 0; i < NumThreads; ++i){ boost::interprocess::scoped_lock lock(mutex); while(count == queue_size){ ++waiting_writer; @@ -347,10 +323,12 @@ void do_test_condition_queue_notify_one(void) if(waiting_readers) cond_empty.notify_one(); } - thgroup.join_all(); - BOOST_INTERPROCES_CHECK(count == 0); - BOOST_INTERPROCES_CHECK(waiting_readers == 0); - BOOST_INTERPROCES_CHECK(waiting_writer == 0); + for(int i = 0; i< NumThreads; ++i){ + boost::interprocess::ipcdetail::thread_join(thgroup[i]); + } + BOOST_INTERPROCESS_CHECK(count == 0); + BOOST_INTERPROCESS_CHECK(waiting_readers == 0); + BOOST_INTERPROCESS_CHECK(waiting_writer == 0); } } @@ -370,15 +348,14 @@ void do_test_condition_queue_notify_all(void) waiting_readers = 0; waiting_writer = 0; - boost::thread_group thgroup; - int i; - for(i = 0; i< NumThreads; ++i){ + boost::interprocess::ipcdetail::OS_thread_t thgroup[NumThreads]; + for(int i = 0; i< NumThreads; ++i){ condition_func func(cond_full, cond_empty, mutex); - thgroup.create_thread(func); + boost::interprocess::ipcdetail::thread_launch(thgroup[i], func); } //Fill queue to the max size and notify all several times - for(i = 0; i < NumThreads; ++i){ + for(int i = 0; i < NumThreads; ++i){ boost::interprocess::scoped_locklock(mutex); while(count == queue_size){ ++waiting_writer; @@ -390,10 +367,12 @@ void do_test_condition_queue_notify_all(void) if(waiting_readers) cond_empty.notify_all(); } - thgroup.join_all(); - BOOST_INTERPROCES_CHECK(count == 0); - BOOST_INTERPROCES_CHECK(waiting_readers == 0); - BOOST_INTERPROCES_CHECK(waiting_writer == 0); + for(int i = 0; i< NumThreads; ++i){ + boost::interprocess::ipcdetail::thread_join(thgroup[i]); + } + BOOST_INTERPROCESS_CHECK(count == 0); + BOOST_INTERPROCESS_CHECK(waiting_readers == 0); + BOOST_INTERPROCESS_CHECK(waiting_writer == 0); } } diff --git a/test/message_queue_test.cpp b/test/message_queue_test.cpp index f9e7b79..8261d45 100644 --- a/test/message_queue_test.cpp +++ b/test/message_queue_test.cpp @@ -15,10 +15,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include "get_process_id_name.hpp" @@ -251,8 +251,9 @@ bool test_buffer_overflow() pmessage_queue = ptr.get(); //Launch the receiver thread - boost::thread thread(&receiver); - boost::thread::yield(); + boost::interprocess::ipcdetail::OS_thread_t thread; + boost::interprocess::ipcdetail::thread_launch(thread, &receiver); + boost::interprocess::ipcdetail::thread_yield(); int nummsg = NumMsg; @@ -260,7 +261,7 @@ bool test_buffer_overflow() pmessage_queue->send(msgsend, MsgSize, 0); } - thread.join(); + boost::interprocess::ipcdetail::thread_join(thread); } boost::interprocess::message_queue::remove(test::get_process_id_name()); return true; diff --git a/test/mutex_test_template.hpp b/test/mutex_test_template.hpp index c41abe3..eb96e86 100644 --- a/test/mutex_test_template.hpp +++ b/test/mutex_test_template.hpp @@ -25,7 +25,7 @@ #include #include "boost_interprocess_check.hpp" #include "util.hpp" -#include +#include #include #include #include @@ -46,16 +46,16 @@ struct test_lock // Test the lock's constructors. { lock_type lock(interprocess_mutex, boost::interprocess::defer_lock); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); } lock_type lock(interprocess_mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); // Test the lock and unlock methods. lock.unlock(); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); lock.lock(); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); } }; @@ -72,24 +72,24 @@ struct test_trylock // Test the lock's constructors. { try_to_lock_type lock(interprocess_mutex, boost::interprocess::try_to_lock); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); } { try_to_lock_type lock(interprocess_mutex, boost::interprocess::defer_lock); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); } try_to_lock_type lock(interprocess_mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); // Test the lock, unlock and trylock methods. lock.unlock(); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); lock.lock(); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); lock.unlock(); - BOOST_INTERPROCES_CHECK(!lock); - BOOST_INTERPROCES_CHECK(lock.try_lock()); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(lock.try_lock()); + BOOST_INTERPROCESS_CHECK(lock ? true : false); } }; @@ -109,25 +109,25 @@ struct test_timedlock boost::posix_time::ptime pt = delay(1*BaseSeconds, 0); timed_lock_type lock(interprocess_mutex, pt); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); } { timed_lock_type lock(interprocess_mutex, boost::interprocess::defer_lock); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); } timed_lock_type lock(interprocess_mutex); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); // Test the lock, unlock and timedlock methods. lock.unlock(); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); lock.lock(); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock ? true : false); lock.unlock(); - BOOST_INTERPROCES_CHECK(!lock); + BOOST_INTERPROCESS_CHECK(!lock); boost::posix_time::ptime pt = delay(3*BaseSeconds, 0); - BOOST_INTERPROCES_CHECK(lock.timed_lock(pt)); - BOOST_INTERPROCES_CHECK(lock ? true : false); + BOOST_INTERPROCESS_CHECK(lock.timed_lock(pt)); + BOOST_INTERPROCESS_CHECK(lock ? true : false); } }; @@ -170,10 +170,10 @@ void lock_and_sleep(void *arg, M &sm) data *pdata = static_cast*>(arg); boost::interprocess::scoped_lock l(sm); if(pdata->m_secs){ - boost::thread::sleep(xsecs(pdata->m_secs)); + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs)); } else{ - boost::thread::sleep(xsecs(2*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); } ++shared_val; @@ -188,10 +188,10 @@ void lock_and_catch_errors(void *arg, M &sm) { boost::interprocess::scoped_lock l(sm); if(pdata->m_secs){ - boost::thread::sleep(xsecs(pdata->m_secs)); + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs)); } else{ - boost::thread::sleep(xsecs(2*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); } ++shared_val; pdata->m_value = shared_val; @@ -208,7 +208,7 @@ void try_lock_and_sleep(void *arg, M &sm) data *pdata = static_cast*>(arg); boost::interprocess::scoped_lock l(sm, boost::interprocess::defer_lock); if (l.try_lock()){ - boost::thread::sleep(xsecs(2*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); ++shared_val; pdata->m_value = shared_val; } @@ -222,7 +222,7 @@ void timed_lock_and_sleep(void *arg, M &sm) boost::interprocess::scoped_lock l (sm, boost::interprocess::defer_lock); if (l.timed_lock(pt)){ - boost::thread::sleep(xsecs(2*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*2*BaseSeconds)); ++shared_val; pdata->m_value = shared_val; } @@ -239,21 +239,24 @@ void test_mutex_lock() data d2(2); // Locker one launches, holds the lock for 2*BaseSeconds seconds. - boost::thread tm1(thread_adapter(&lock_and_sleep, &d1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&lock_and_sleep, &d1, mtx)); //Wait 1*BaseSeconds - boost::thread::sleep(xsecs(1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); // Locker two launches, but it won't hold the lock for 2*BaseSeconds seconds. - boost::thread tm2(thread_adapter(&lock_and_sleep, &d2, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&lock_and_sleep, &d2, mtx)); //Wait completion - tm1.join(); - boost::thread::sleep(xsecs(1*BaseSeconds)); - tm2.join(); + + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_join(tm2); - BOOST_INTERPROCES_CHECK(d1.m_value == 1); - BOOST_INTERPROCES_CHECK(d2.m_value == 2); + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == 2); } template @@ -271,23 +274,25 @@ void test_mutex_lock_timeout() data d2(2, wait_time_s * 2); // Locker one launches, and holds the lock for wait_time_s * 2 seconds. - boost::thread tm1(thread_adapter(&lock_and_sleep, &d1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&lock_and_sleep, &d1, mtx)); //Wait 1*BaseSeconds - boost::thread::sleep(xsecs(wait_time_s)); + boost::interprocess::ipcdetail::thread_sleep((1000*wait_time_s)); // Locker two launches, and attempts to hold the lock for wait_time_s * 2 seconds. - boost::thread tm2(thread_adapter(&lock_and_catch_errors, &d2, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&lock_and_catch_errors, &d2, mtx)); //Wait completion - tm1.join(); - boost::thread::sleep(xsecs(1*BaseSeconds)); - tm2.join(); + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_join(tm2); - BOOST_INTERPROCES_CHECK(d1.m_value == 1); - BOOST_INTERPROCES_CHECK(d2.m_value == -1); - BOOST_INTERPROCES_CHECK(d1.m_error == no_error); - BOOST_INTERPROCES_CHECK(d2.m_error == boost::interprocess::timeout_when_locking_error); + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == -1); + BOOST_INTERPROCESS_CHECK(d1.m_error == no_error); + BOOST_INTERPROCESS_CHECK(d2.m_error == boost::interprocess::timeout_when_locking_error); } template @@ -301,20 +306,23 @@ void test_mutex_try_lock() data d2(2); // Locker one launches, holds the lock for 2*BaseSeconds seconds. - boost::thread tm1(thread_adapter(&try_lock_and_sleep, &d1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&try_lock_and_sleep, &d1, mtx)); //Wait 1*BaseSeconds - boost::thread::sleep(xsecs(1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); // Locker two launches, but it should fail acquiring the lock - boost::thread tm2(thread_adapter(&try_lock_and_sleep, &d2, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&try_lock_and_sleep, &d2, mtx)); //Wait completion - tm1.join(); - tm2.join(); + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_join(tm2); + //Only the first should succeed locking - BOOST_INTERPROCES_CHECK(d1.m_value == 1); - BOOST_INTERPROCES_CHECK(d2.m_value == -1); + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == -1); } template @@ -329,21 +337,23 @@ void test_mutex_timed_lock() data d2(2, 2*BaseSeconds); // Locker one launches, holds the lock for 2*BaseSeconds seconds. - boost::thread tm1(thread_adapter(&timed_lock_and_sleep, &d1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm1; + boost::interprocess::ipcdetail::thread_launch(tm1, thread_adapter(&timed_lock_and_sleep, &d1, mtx)); //Wait 1*BaseSeconds - boost::thread::sleep(xsecs(1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); // Locker two launches, holds the lock for 2*BaseSeconds seconds. - boost::thread tm2(thread_adapter(&timed_lock_and_sleep, &d2, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tm2; + boost::interprocess::ipcdetail::thread_launch(tm2, thread_adapter(&timed_lock_and_sleep, &d2, mtx)); //Wait completion - tm1.join(); - tm2.join(); + boost::interprocess::ipcdetail::thread_join(tm1); + boost::interprocess::ipcdetail::thread_join(tm2); //Both should succeed locking - BOOST_INTERPROCES_CHECK(d1.m_value == 1); - BOOST_INTERPROCES_CHECK(d2.m_value == 2); + BOOST_INTERPROCESS_CHECK(d1.m_value == 1); + BOOST_INTERPROCESS_CHECK(d2.m_value == 2); } template diff --git a/test/named_creation_template.hpp b/test/named_creation_template.hpp index ee34aa6..1e00299 100644 --- a/test/named_creation_template.hpp +++ b/test/named_creation_template.hpp @@ -32,7 +32,7 @@ inline void create_then_open_then_open_or_create() } catch(...){ //This shouldn't throw so show the error - BOOST_INTERPROCES_CHECK( false ); + BOOST_INTERPROCESS_CHECK( false ); } } @@ -45,7 +45,7 @@ inline void open_or_create_then_create() NamedResource nresource2(create_only); } catch(interprocess_exception &err){ - BOOST_INTERPROCES_CHECK(err.get_error_code() == already_exists_error); + BOOST_INTERPROCESS_CHECK(err.get_error_code() == already_exists_error); } } @@ -57,11 +57,11 @@ inline void dont_create_and_open() NamedResource nresource1(open_only); } catch(interprocess_exception &err){ - BOOST_INTERPROCES_CHECK(err.get_error_code() == not_found_error); + BOOST_INTERPROCESS_CHECK(err.get_error_code() == not_found_error); return; } //The mutex should not exist - BOOST_INTERPROCES_CHECK(false); + BOOST_INTERPROCESS_CHECK(false); } template diff --git a/test/named_semaphore_test.cpp b/test/named_semaphore_test.cpp index c5dc02b..70c88e3 100644 --- a/test/named_semaphore_test.cpp +++ b/test/named_semaphore_test.cpp @@ -86,16 +86,16 @@ bool test_named_semaphore_specific() } { named_semaphore sem(open_only, SemName); - BOOST_INTERPROCES_CHECK(sem.try_wait() == true); - BOOST_INTERPROCES_CHECK(sem.try_wait() == true); - BOOST_INTERPROCES_CHECK(sem.try_wait() == true); - BOOST_INTERPROCES_CHECK(sem.try_wait() == false); + BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); + BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); + BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); + BOOST_INTERPROCESS_CHECK(sem.try_wait() == false); sem.post(); } { named_semaphore sem(open_only, SemName); - BOOST_INTERPROCES_CHECK(sem.try_wait() == true); - BOOST_INTERPROCES_CHECK(sem.try_wait() == false); + BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); + BOOST_INTERPROCESS_CHECK(sem.try_wait() == false); } named_semaphore::remove(SemName); diff --git a/test/sharable_mutex_test_template.hpp b/test/sharable_mutex_test_template.hpp index 3fc5e98..3c14c7a 100644 --- a/test/sharable_mutex_test_template.hpp +++ b/test/sharable_mutex_test_template.hpp @@ -24,8 +24,7 @@ #include #include -#include -#include +#include #include "boost_interprocess_check.hpp" #include #include @@ -41,7 +40,7 @@ void plain_exclusive(void *arg, SM &sm) { data *pdata = static_cast*>(arg); boost::interprocess::scoped_lock l(sm); - boost::thread::sleep(xsecs(3*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds)); shared_val += 10; pdata->m_value = shared_val; } @@ -52,7 +51,7 @@ void plain_shared(void *arg, SM &sm) data *pdata = static_cast*>(arg); boost::interprocess::sharable_lock l(sm); if(pdata->m_secs){ - boost::thread::sleep(xsecs(pdata->m_secs*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds)); } pdata->m_value = shared_val; } @@ -63,7 +62,7 @@ void try_exclusive(void *arg, SM &sm) data *pdata = static_cast*>(arg); boost::interprocess::scoped_lock l(sm, boost::interprocess::defer_lock); if (l.try_lock()){ - boost::thread::sleep(xsecs(3*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds)); shared_val += 10; pdata->m_value = shared_val; } @@ -76,7 +75,7 @@ void try_shared(void *arg, SM &sm) boost::interprocess::sharable_lock l(sm, boost::interprocess::defer_lock); if (l.try_lock()){ if(pdata->m_secs){ - boost::thread::sleep(xsecs(pdata->m_secs*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds)); } pdata->m_value = shared_val; } @@ -90,7 +89,7 @@ void timed_exclusive(void *arg, SM &sm) boost::interprocess::scoped_lock l (sm, boost::interprocess::defer_lock); if (l.timed_lock(pt)){ - boost::thread::sleep(xsecs(3*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*3*BaseSeconds)); shared_val += 10; pdata->m_value = shared_val; } @@ -105,7 +104,7 @@ void timed_shared(void *arg, SM &sm) l(sm, boost::interprocess::defer_lock); if (l.timed_lock(pt)){ if(pdata->m_secs){ - boost::thread::sleep(xsecs(pdata->m_secs*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*pdata->m_secs*BaseSeconds)); } pdata->m_value = shared_val; } @@ -123,28 +122,32 @@ void test_plain_sharable_mutex() data e2(2); // Writer one launches, holds the lock for 3*BaseSeconds seconds. - boost::thread tw1(thread_adapter(plain_exclusive, &e1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tw1; + boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter(plain_exclusive, &e1, mtx)); // Writer two launches, tries to grab the lock, "clearly" // after Writer one will already be holding it. - boost::thread::sleep(xsecs(1*BaseSeconds)); - boost::thread tw2(thread_adapter(plain_exclusive, &e2, mtx)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::OS_thread_t tw2; + boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter(plain_exclusive, &e2, mtx)); // Reader one launches, "clearly" after writer two, and "clearly" // while writer 1 still holds the lock - boost::thread::sleep(xsecs(1*BaseSeconds)); - boost::thread thr1(thread_adapter(plain_shared,&s1, mtx)); - boost::thread thr2(thread_adapter(plain_shared,&s2, mtx)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::OS_thread_t thr1; + boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter(plain_shared,&s1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t thr2; + boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter(plain_shared,&s2, mtx)); - thr2.join(); - thr1.join(); - tw2.join(); - tw1.join(); + boost::interprocess::ipcdetail::thread_join(thr2); + boost::interprocess::ipcdetail::thread_join(thr1); + boost::interprocess::ipcdetail::thread_join(tw2); + boost::interprocess::ipcdetail::thread_join(tw1); //We can only assure that the writer will be first - BOOST_INTERPROCES_CHECK(e1.m_value == 10); + BOOST_INTERPROCESS_CHECK(e1.m_value == 10); //A that we will execute all - BOOST_INTERPROCES_CHECK(s1.m_value == 20 || s2.m_value == 20 || e2.m_value == 20); + BOOST_INTERPROCESS_CHECK(s1.m_value == 20 || s2.m_value == 20 || e2.m_value == 20); } { @@ -157,25 +160,30 @@ void test_plain_sharable_mutex() data e2(2); //We launch 2 readers, that will block for 3*BaseTime seconds - boost::thread thr1(thread_adapter(plain_shared,&s1, mtx)); - boost::thread thr2(thread_adapter(plain_shared,&s2, mtx)); + boost::interprocess::ipcdetail::OS_thread_t thr1; + boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter(plain_shared,&s1, mtx)); + boost::interprocess::ipcdetail::OS_thread_t thr2; + boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter(plain_shared,&s2, mtx)); //Make sure they try to hold the sharable lock - boost::thread::sleep(xsecs(1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); // We launch two writers, that should block until the readers end - boost::thread tw1(thread_adapter(plain_exclusive,&e1, mtx)); - boost::thread tw2(thread_adapter(plain_exclusive,&e2, mtx)); + boost::interprocess::ipcdetail::OS_thread_t tw1; + boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter(plain_exclusive,&e1, mtx)); - thr2.join(); - thr1.join(); - tw2.join(); - tw1.join(); + boost::interprocess::ipcdetail::OS_thread_t tw2; + boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter(plain_exclusive,&e2, mtx)); + + boost::interprocess::ipcdetail::thread_join(thr2); + boost::interprocess::ipcdetail::thread_join(thr1); + boost::interprocess::ipcdetail::thread_join(tw2); + boost::interprocess::ipcdetail::thread_join(tw1); //We can only assure that the shared will finish first... - BOOST_INTERPROCES_CHECK(s1.m_value == 0 || s2.m_value == 0); + BOOST_INTERPROCESS_CHECK(s1.m_value == 0 || s2.m_value == 0); //...and writers will be mutually excluded after readers - BOOST_INTERPROCES_CHECK((e1.m_value == 10 && e2.m_value == 20) || + BOOST_INTERPROCESS_CHECK((e1.m_value == 10 && e2.m_value == 20) || (e1.m_value == 20 && e2.m_value == 10) ); } } @@ -194,24 +202,26 @@ void test_try_sharable_mutex() shared_val = 0; // Writer one launches, holds the lock for 3*BaseSeconds seconds. - - boost::thread tw1(thread_adapter(try_exclusive,&e1,mtx)); + boost::interprocess::ipcdetail::OS_thread_t tw1; + boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter(try_exclusive,&e1,mtx)); // Reader one launches, "clearly" after writer #1 holds the lock // and before it releases the lock. - boost::thread::sleep(xsecs(1*BaseSeconds)); - boost::thread thr1(thread_adapter(try_shared,&s1,mtx)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); + boost::interprocess::ipcdetail::OS_thread_t thr1; + boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter(try_shared,&s1,mtx)); // Writer two launches in the same timeframe. - boost::thread tw2(thread_adapter(try_exclusive,&e2,mtx)); + boost::interprocess::ipcdetail::OS_thread_t tw2; + boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter(try_exclusive,&e2,mtx)); - tw2.join(); - thr1.join(); - tw1.join(); + boost::interprocess::ipcdetail::thread_join(tw2); + boost::interprocess::ipcdetail::thread_join(thr1); + boost::interprocess::ipcdetail::thread_join(tw1); - BOOST_INTERPROCES_CHECK(e1.m_value == 10); - BOOST_INTERPROCES_CHECK(s1.m_value == -1); // Try would return w/o waiting - BOOST_INTERPROCES_CHECK(e2.m_value == -1); // Try would return w/o waiting + BOOST_INTERPROCESS_CHECK(e1.m_value == 10); + BOOST_INTERPROCESS_CHECK(s1.m_value == -1); // Try would return w/o waiting + BOOST_INTERPROCESS_CHECK(e2.m_value == -1); // Try would return w/o waiting } template @@ -228,31 +238,36 @@ void test_timed_sharable_mutex() shared_val = 0; // Writer one will hold the lock for 3*BaseSeconds seconds. - boost::thread tw1(thread_adapter(timed_exclusive,&e1,mtx)); + boost::interprocess::ipcdetail::OS_thread_t tw1; + boost::interprocess::ipcdetail::thread_launch(tw1, thread_adapter(timed_exclusive,&e1,mtx)); - boost::thread::sleep(xsecs(1*BaseSeconds)); + boost::interprocess::ipcdetail::thread_sleep((1000*1*BaseSeconds)); // Writer two will "clearly" try for the lock after the readers // have tried for it. Writer will wait up 1*BaseSeconds seconds for the lock. // This write will fail. - boost::thread tw2(thread_adapter(timed_exclusive,&e2,mtx)); + boost::interprocess::ipcdetail::OS_thread_t tw2; + boost::interprocess::ipcdetail::thread_launch(tw2, thread_adapter(timed_exclusive,&e2,mtx)); // Readers one and two will "clearly" try for the lock after writer // one already holds it. 1st reader will wait 1*BaseSeconds seconds, and will fail // to get the lock. 2nd reader will wait 3*BaseSeconds seconds, and will get // the lock. - boost::thread thr1(thread_adapter(timed_shared,&s1,mtx)); - boost::thread thr2(thread_adapter(timed_shared,&s2,mtx)); + boost::interprocess::ipcdetail::OS_thread_t thr1; + boost::interprocess::ipcdetail::thread_launch(thr1, thread_adapter(timed_shared,&s1,mtx)); - tw1.join(); - thr1.join(); - thr2.join(); - tw2.join(); + boost::interprocess::ipcdetail::OS_thread_t thr2; + boost::interprocess::ipcdetail::thread_launch(thr2, thread_adapter(timed_shared,&s2,mtx)); - BOOST_INTERPROCES_CHECK(e1.m_value == 10); - BOOST_INTERPROCES_CHECK(s1.m_value == -1); - BOOST_INTERPROCES_CHECK(s2.m_value == 10); - BOOST_INTERPROCES_CHECK(e2.m_value == -1); + boost::interprocess::ipcdetail::thread_join(tw1); + boost::interprocess::ipcdetail::thread_join(thr1); + boost::interprocess::ipcdetail::thread_join(thr2); + boost::interprocess::ipcdetail::thread_join(tw2); + + BOOST_INTERPROCESS_CHECK(e1.m_value == 10); + BOOST_INTERPROCESS_CHECK(s1.m_value == -1); + BOOST_INTERPROCESS_CHECK(s2.m_value == 10); + BOOST_INTERPROCESS_CHECK(e2.m_value == -1); } template diff --git a/test/util.hpp b/test/util.hpp index 1580c9f..1cdc8be 100644 --- a/test/util.hpp +++ b/test/util.hpp @@ -24,8 +24,6 @@ #include #include #include -#include -#include #include #include @@ -61,30 +59,18 @@ inline bool in_range(const boost::posix_time::ptime& xt, int secs=1) return (xt > min) && (max > xt); } -boost::xtime xsecs(int secs) -{ - boost::xtime ret; - #if BOOST_VERSION >= 105100 //TIME_UTC is a macro in C11, breaking change in Boost.Thread - boost::xtime_get(&ret, boost::TIME_UTC_); - #else - boost::xtime_get(&ret, boost::TIME_UTC); - #endif - ret.sec += secs; - return ret; -} - template class thread_adapter { public: thread_adapter(void (*func)(void*, P &), void* param1, P ¶m2) - : _func(func), _param1(param1) ,_param2(param2){ } - void operator()() const { _func(_param1, _param2); } + : func_(func), param1_(param1) ,param2_(param2){ } + void operator()() const { func_(param1_, param2_); } private: - void (*_func)(void*, P &); - void* _param1; - P& _param2; + void (*func_)(void*, P &); + void* param1_; + P& param2_; }; template