mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
4 Commits
feature/up
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80d7365dd6 | ||
|
|
1ddf36c500 | ||
|
|
9d24b8042b | ||
|
|
87b3a1095b |
@@ -44,6 +44,8 @@ functions.
|
||||
but did not lock it on construction. This facility has now been replaced with the constructor that takes a
|
||||
`boost::defer_lock_type` as the second parameter: ``boost::mutex::scoped_lock some_lock(some_mutex,boost::defer_lock);``
|
||||
|
||||
* The `locked()` member function of the `scoped_lock` types has been renamed to __owns_lock_ref__.
|
||||
|
||||
* The broken `boost::read_write_mutex` has been replaced with __shared_mutex__.
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// (C) Copyright 2008 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)
|
||||
@@ -10,12 +11,15 @@
|
||||
#define BOOST_THREAD_WEK01082003_HPP
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -400,13 +400,16 @@ namespace boost
|
||||
{
|
||||
lock();
|
||||
}
|
||||
upgrade_lock(Mutex& m_,bool do_lock):
|
||||
upgrade_lock(Mutex& m_,adopt_lock_t):
|
||||
m(&m_),is_locked(true)
|
||||
{}
|
||||
upgrade_lock(Mutex& m_,defer_lock_t):
|
||||
m(&m_),is_locked(false)
|
||||
{}
|
||||
upgrade_lock(Mutex& m_,try_to_lock_t):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
try_lock();
|
||||
}
|
||||
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
|
||||
@@ -58,6 +58,12 @@ namespace boost
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
}
|
||||
|
||||
typedef pthread_cond_t* native_handle_type;
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return &cond;
|
||||
}
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
};
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace boost
|
||||
{
|
||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
BOOST_ASSERT(!res || res==ETIMEDOUT);
|
||||
return !res;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -118,6 +118,12 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_shared(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
void unlock_shared()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
@@ -196,6 +202,12 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
@@ -271,6 +283,12 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_upgrade(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
@@ -214,6 +214,9 @@ namespace boost
|
||||
static void sleep(const system_time& xt);
|
||||
static void yield();
|
||||
|
||||
typedef pthread_t native_handle_type;
|
||||
native_handle_type native_handle();
|
||||
|
||||
// extensions
|
||||
void interrupt();
|
||||
bool interruption_requested() const;
|
||||
|
||||
@@ -34,6 +34,12 @@ namespace boost
|
||||
list_entry():
|
||||
semaphore(0),count(0),notified(0)
|
||||
{}
|
||||
|
||||
void release(unsigned count_to_release=1)
|
||||
{
|
||||
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned,generation_count=3);
|
||||
@@ -41,6 +47,13 @@ namespace boost
|
||||
list_entry generations[generation_count];
|
||||
detail::win32::handle wake_sem;
|
||||
|
||||
void wake_waiters(long count_to_wake)
|
||||
{
|
||||
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
|
||||
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
}
|
||||
|
||||
|
||||
static bool no_waiters(list_entry const& entry)
|
||||
{
|
||||
return entry.count==0;
|
||||
@@ -51,7 +64,7 @@ namespace boost
|
||||
list_entry* const last_active_entry=std::remove_if(generations,generations+generation_count,no_waiters);
|
||||
if(last_active_entry==generations+generation_count)
|
||||
{
|
||||
broadcast_entry(generations[generation_count-1],false);
|
||||
broadcast_entry(generations[generation_count-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -69,15 +82,9 @@ namespace boost
|
||||
generations[0]=list_entry();
|
||||
}
|
||||
|
||||
void broadcast_entry(list_entry& entry,bool wake)
|
||||
void broadcast_entry(list_entry& entry)
|
||||
{
|
||||
long const count_to_wake=entry.count;
|
||||
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
|
||||
if(wake)
|
||||
{
|
||||
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
}
|
||||
detail::win32::ReleaseSemaphore(entry.semaphore,count_to_wake,0);
|
||||
entry.release(entry.count);
|
||||
entry.count=0;
|
||||
dispose_entry(entry);
|
||||
}
|
||||
@@ -124,6 +131,7 @@ namespace boost
|
||||
void start_wait_loop_first_time(relocker<lock_type>& locker,
|
||||
detail::win32::handle_manager& local_wake_sem)
|
||||
{
|
||||
detail::interlocked_write_release(&total_count,total_count+1);
|
||||
locker.unlock();
|
||||
if(!wake_sem)
|
||||
{
|
||||
@@ -141,6 +149,15 @@ namespace boost
|
||||
active_generation_count=1;
|
||||
}
|
||||
}
|
||||
|
||||
void ensure_generation_present()
|
||||
{
|
||||
if(!generations[0].semaphore)
|
||||
{
|
||||
generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
BOOST_ASSERT(generations[0].semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
void start_wait_loop(relocker<lock_type>& locker,
|
||||
@@ -148,16 +165,11 @@ namespace boost
|
||||
detail::win32::handle_manager& sem)
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
detail::interlocked_write_release(&total_count,total_count+1);
|
||||
if(!local_wake_sem)
|
||||
{
|
||||
start_wait_loop_first_time(locker,local_wake_sem);
|
||||
}
|
||||
if(!generations[0].semaphore)
|
||||
{
|
||||
generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
BOOST_ASSERT(generations[0].semaphore);
|
||||
}
|
||||
ensure_generation_present();
|
||||
++generations[0].count;
|
||||
sem=detail::win32::duplicate_handle(generations[0].semaphore);
|
||||
}
|
||||
@@ -222,15 +234,22 @@ namespace boost
|
||||
if(detail::interlocked_read_acquire(&total_count))
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
detail::win32::ReleaseSemaphore(wake_sem,1,0);
|
||||
if(!total_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
wake_waiters(1);
|
||||
|
||||
unsigned waiting_count=0;
|
||||
|
||||
for(unsigned generation=active_generation_count;generation!=0;--generation)
|
||||
{
|
||||
list_entry& entry=generations[generation-1];
|
||||
waiting_count+=entry.count;
|
||||
if(entry.count)
|
||||
{
|
||||
detail::interlocked_write_release(&total_count,total_count-1);
|
||||
entry.notified=true;
|
||||
detail::win32::ReleaseSemaphore(entry.semaphore,1,0);
|
||||
entry.release();
|
||||
if(!--entry.count)
|
||||
{
|
||||
dispose_entry(entry);
|
||||
@@ -241,6 +260,12 @@ namespace boost
|
||||
}
|
||||
}
|
||||
}
|
||||
if(waiting_count<=total_count)
|
||||
{
|
||||
shift_generations_down();
|
||||
ensure_generation_present();
|
||||
generations[0].release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,14 +274,23 @@ namespace boost
|
||||
if(detail::interlocked_read_acquire(&total_count))
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
long waiting_count=total_count;
|
||||
|
||||
wake_waiters(total_count);
|
||||
for(unsigned generation=active_generation_count;generation!=0;--generation)
|
||||
{
|
||||
list_entry& entry=generations[generation-1];
|
||||
if(entry.count)
|
||||
{
|
||||
broadcast_entry(entry,true);
|
||||
waiting_count-=entry.count;
|
||||
broadcast_entry(entry);
|
||||
}
|
||||
}
|
||||
if(waiting_count)
|
||||
{
|
||||
ensure_generation_present();
|
||||
generations[0].release(waiting_count);
|
||||
}
|
||||
active_generation_count=0;
|
||||
}
|
||||
}
|
||||
@@ -265,9 +299,18 @@ namespace boost
|
||||
}
|
||||
|
||||
class condition_variable:
|
||||
public detail::basic_condition_variable
|
||||
private detail::basic_condition_variable
|
||||
{
|
||||
private:
|
||||
condition_variable(condition_variable&);
|
||||
void operator=(condition_variable&);
|
||||
public:
|
||||
condition_variable()
|
||||
{}
|
||||
|
||||
using detail::basic_condition_variable::notify_one;
|
||||
using detail::basic_condition_variable::notify_all;
|
||||
|
||||
void wait(unique_lock<mutex>& m)
|
||||
{
|
||||
do_wait(m,detail::timeout::sentinel());
|
||||
@@ -313,9 +356,18 @@ namespace boost
|
||||
};
|
||||
|
||||
class condition_variable_any:
|
||||
public detail::basic_condition_variable
|
||||
private detail::basic_condition_variable
|
||||
{
|
||||
private:
|
||||
condition_variable_any(condition_variable_any&);
|
||||
void operator=(condition_variable_any&);
|
||||
public:
|
||||
condition_variable_any()
|
||||
{}
|
||||
|
||||
using detail::basic_condition_variable::notify_one;
|
||||
using detail::basic_condition_variable::notify_all;
|
||||
|
||||
template<typename lock_type>
|
||||
void wait(lock_type& m)
|
||||
{
|
||||
|
||||
@@ -120,6 +120,12 @@ namespace boost
|
||||
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock_shared(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock_shared(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
bool timed_lock_shared(boost::system_time const& wait_until)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
@@ -269,6 +275,12 @@ namespace boost
|
||||
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
bool timed_lock(boost::system_time const& wait_until)
|
||||
{
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
0
src/pthread/once.cpp
Executable file → Normal file
0
src/pthread/once.cpp
Executable file → Normal file
@@ -472,6 +472,21 @@ namespace boost
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
thread::native_handle_type thread::native_handle()
|
||||
{
|
||||
detail::thread_data_ptr const local_thread_info=get_thread_info();
|
||||
if(local_thread_info)
|
||||
{
|
||||
lock_guard<mutex> lk(local_thread_info->data_mutex);
|
||||
return local_thread_info->thread_handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pthread_t();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace this_thread
|
||||
|
||||
@@ -51,6 +51,7 @@ rule thread-run ( sources )
|
||||
[ thread-run test_barrier.cpp ]
|
||||
[ thread-run test_shared_mutex.cpp ]
|
||||
[ thread-run test_shared_mutex_part_2.cpp ]
|
||||
[ thread-run test_shared_mutex_timed_locks.cpp ]
|
||||
[ thread-run test_lock_concept.cpp ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -66,5 +66,67 @@ private:
|
||||
void operator=(locking_thread&);
|
||||
};
|
||||
|
||||
class simple_writing_thread
|
||||
{
|
||||
boost::shared_mutex& rwm;
|
||||
boost::mutex& finish_mutex;
|
||||
boost::mutex& unblocked_mutex;
|
||||
unsigned& unblocked_count;
|
||||
|
||||
void operator=(simple_writing_thread&);
|
||||
|
||||
public:
|
||||
simple_writing_thread(boost::shared_mutex& rwm_,
|
||||
boost::mutex& finish_mutex_,
|
||||
boost::mutex& unblocked_mutex_,
|
||||
unsigned& unblocked_count_):
|
||||
rwm(rwm_),finish_mutex(finish_mutex_),
|
||||
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
boost::unique_lock<boost::shared_mutex> lk(rwm);
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock ulk(unblocked_mutex);
|
||||
++unblocked_count;
|
||||
}
|
||||
|
||||
boost::mutex::scoped_lock flk(finish_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
class simple_reading_thread
|
||||
{
|
||||
boost::shared_mutex& rwm;
|
||||
boost::mutex& finish_mutex;
|
||||
boost::mutex& unblocked_mutex;
|
||||
unsigned& unblocked_count;
|
||||
|
||||
void operator=(simple_reading_thread&);
|
||||
|
||||
public:
|
||||
simple_reading_thread(boost::shared_mutex& rwm_,
|
||||
boost::mutex& finish_mutex_,
|
||||
boost::mutex& unblocked_mutex_,
|
||||
unsigned& unblocked_count_):
|
||||
rwm(rwm_),finish_mutex(finish_mutex_),
|
||||
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lk(rwm);
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock ulk(unblocked_mutex);
|
||||
++unblocked_count;
|
||||
}
|
||||
|
||||
boost::mutex::scoped_lock flk(finish_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -159,6 +159,47 @@ void do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate(
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
boost::mutex multiple_wake_mutex;
|
||||
boost::condition_variable multiple_wake_cond;
|
||||
unsigned multiple_wake_count=0;
|
||||
|
||||
void wait_for_condvar_and_increase_count()
|
||||
{
|
||||
boost::mutex::scoped_lock lk(multiple_wake_mutex);
|
||||
multiple_wake_cond.wait(lk);
|
||||
++multiple_wake_count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void do_test_notify_all_following_notify_one_wakes_all_threads()
|
||||
{
|
||||
boost::thread thread1(wait_for_condvar_and_increase_count);
|
||||
boost::thread thread2(wait_for_condvar_and_increase_count);
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
multiple_wake_cond.notify_one();
|
||||
|
||||
boost::thread thread3(wait_for_condvar_and_increase_count);
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
multiple_wake_cond.notify_one();
|
||||
multiple_wake_cond.notify_all();
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lk(multiple_wake_mutex);
|
||||
BOOST_CHECK(multiple_wake_count==3);
|
||||
}
|
||||
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
thread3.join();
|
||||
}
|
||||
|
||||
void test_condition_notify_all()
|
||||
{
|
||||
timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
|
||||
@@ -166,6 +207,7 @@ void test_condition_notify_all()
|
||||
timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds);
|
||||
timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds);
|
||||
timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds);
|
||||
timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -92,6 +92,47 @@ void do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate(
|
||||
BOOST_CHECK(data.woken);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
boost::mutex multiple_wake_mutex;
|
||||
boost::condition_variable multiple_wake_cond;
|
||||
unsigned multiple_wake_count=0;
|
||||
|
||||
void wait_for_condvar_and_increase_count()
|
||||
{
|
||||
boost::mutex::scoped_lock lk(multiple_wake_mutex);
|
||||
multiple_wake_cond.wait(lk);
|
||||
++multiple_wake_count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void do_test_multiple_notify_one_calls_wakes_multiple_threads()
|
||||
{
|
||||
boost::thread thread1(wait_for_condvar_and_increase_count);
|
||||
boost::thread thread2(wait_for_condvar_and_increase_count);
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
multiple_wake_cond.notify_one();
|
||||
|
||||
boost::thread thread3(wait_for_condvar_and_increase_count);
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
multiple_wake_cond.notify_one();
|
||||
multiple_wake_cond.notify_one();
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lk(multiple_wake_mutex);
|
||||
BOOST_CHECK(multiple_wake_count==3);
|
||||
}
|
||||
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
thread3.join();
|
||||
}
|
||||
|
||||
void test_condition_notify_one()
|
||||
{
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
|
||||
@@ -99,6 +140,7 @@ void test_condition_notify_one()
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex);
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
|
||||
timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
|
||||
timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -107,40 +107,6 @@ void test_can_lock_upgrade_if_currently_locked_shared()
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class simple_writing_thread
|
||||
{
|
||||
boost::shared_mutex& rwm;
|
||||
boost::mutex& finish_mutex;
|
||||
boost::mutex& unblocked_mutex;
|
||||
unsigned& unblocked_count;
|
||||
|
||||
void operator=(simple_writing_thread&);
|
||||
|
||||
public:
|
||||
simple_writing_thread(boost::shared_mutex& rwm_,
|
||||
boost::mutex& finish_mutex_,
|
||||
boost::mutex& unblocked_mutex_,
|
||||
unsigned& unblocked_count_):
|
||||
rwm(rwm_),finish_mutex(finish_mutex_),
|
||||
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
boost::unique_lock<boost::shared_mutex> lk(rwm);
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock ulk(unblocked_mutex);
|
||||
++unblocked_count;
|
||||
}
|
||||
|
||||
boost::mutex::scoped_lock flk(finish_mutex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
|
||||
{
|
||||
|
||||
@@ -175,40 +141,6 @@ void test_if_no_thread_has_lock_try_lock_shared_returns_true()
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class simple_reading_thread
|
||||
{
|
||||
boost::shared_mutex& rwm;
|
||||
boost::mutex& finish_mutex;
|
||||
boost::mutex& unblocked_mutex;
|
||||
unsigned& unblocked_count;
|
||||
|
||||
void operator=(simple_reading_thread&);
|
||||
|
||||
public:
|
||||
simple_reading_thread(boost::shared_mutex& rwm_,
|
||||
boost::mutex& finish_mutex_,
|
||||
boost::mutex& unblocked_mutex_,
|
||||
unsigned& unblocked_count_):
|
||||
rwm(rwm_),finish_mutex(finish_mutex_),
|
||||
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
|
||||
{}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lk(rwm);
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock ulk(unblocked_mutex);
|
||||
++unblocked_count;
|
||||
}
|
||||
|
||||
boost::mutex::scoped_lock flk(finish_mutex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
|
||||
{
|
||||
|
||||
@@ -232,33 +164,6 @@ void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
|
||||
writer.join();
|
||||
}
|
||||
|
||||
void test_timed_lock_shared_times_out_if_write_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
unsigned unblocked_count=0;
|
||||
boost::mutex::scoped_lock finish_lock(finish_mutex);
|
||||
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
|
||||
boost::thread::sleep(delay(1));
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(2000);
|
||||
boost::posix_time::milliseconds const timeout_resolution(20);
|
||||
bool const timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
|
||||
BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
finish_lock.unlock();
|
||||
writer.join();
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test =
|
||||
@@ -269,7 +174,6 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
|
||||
test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
|
||||
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
235
test/test_shared_mutex_timed_locks.cpp
Normal file
235
test/test_shared_mutex_timed_locks.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
// (C) Copyright 2006-7 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 <boost/test/unit_test.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include "util.inl"
|
||||
#include "shared_mutex_locking_thread.hpp"
|
||||
|
||||
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
|
||||
{ \
|
||||
boost::mutex::scoped_lock lock(mutex_name); \
|
||||
BOOST_CHECK_EQUAL(value,expected_value); \
|
||||
}
|
||||
|
||||
|
||||
void test_timed_lock_shared_times_out_if_write_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
unsigned unblocked_count=0;
|
||||
boost::mutex::scoped_lock finish_lock(finish_mutex);
|
||||
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
|
||||
boost::thread::sleep(delay(1));
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(500);
|
||||
boost::posix_time::milliseconds const timeout_resolution(50);
|
||||
bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
|
||||
BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
boost::posix_time::milliseconds const wait_duration(500);
|
||||
boost::system_time const timeout2=boost::get_system_time()+wait_duration;
|
||||
timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration);
|
||||
BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
finish_lock.unlock();
|
||||
writer.join();
|
||||
}
|
||||
|
||||
void test_timed_lock_shared_succeeds_if_no_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(500);
|
||||
boost::posix_time::milliseconds const timeout_resolution(50);
|
||||
bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
|
||||
BOOST_CHECK(boost::get_system_time()<timeout);
|
||||
BOOST_CHECK(timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
boost::posix_time::milliseconds const wait_duration(500);
|
||||
boost::system_time const timeout2=boost::get_system_time()+wait_duration;
|
||||
timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration);
|
||||
BOOST_CHECK(boost::get_system_time()<timeout2);
|
||||
BOOST_CHECK(timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_timed_lock_shared_succeeds_if_read_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
unsigned unblocked_count=0;
|
||||
boost::mutex::scoped_lock finish_lock(finish_mutex);
|
||||
boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
|
||||
boost::thread::sleep(delay(1));
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(500);
|
||||
boost::posix_time::milliseconds const timeout_resolution(50);
|
||||
bool timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
|
||||
BOOST_CHECK(boost::get_system_time()<timeout);
|
||||
BOOST_CHECK(timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
boost::posix_time::milliseconds const wait_duration(500);
|
||||
boost::system_time const timeout2=boost::get_system_time()+wait_duration;
|
||||
timed_lock_succeeded=rw_mutex.timed_lock_shared(wait_duration);
|
||||
BOOST_CHECK(boost::get_system_time()<timeout2);
|
||||
BOOST_CHECK(timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock_shared();
|
||||
}
|
||||
|
||||
finish_lock.unlock();
|
||||
reader.join();
|
||||
}
|
||||
|
||||
void test_timed_lock_times_out_if_write_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
unsigned unblocked_count=0;
|
||||
boost::mutex::scoped_lock finish_lock(finish_mutex);
|
||||
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
|
||||
boost::thread::sleep(delay(1));
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(500);
|
||||
boost::posix_time::milliseconds const timeout_resolution(50);
|
||||
bool timed_lock_succeeded=rw_mutex.timed_lock(timeout);
|
||||
BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock();
|
||||
}
|
||||
|
||||
boost::posix_time::milliseconds const wait_duration(500);
|
||||
boost::system_time const timeout2=boost::get_system_time()+wait_duration;
|
||||
timed_lock_succeeded=rw_mutex.timed_lock(wait_duration);
|
||||
BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock();
|
||||
}
|
||||
|
||||
finish_lock.unlock();
|
||||
writer.join();
|
||||
}
|
||||
|
||||
void test_timed_lock_succeeds_if_no_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(500);
|
||||
boost::posix_time::milliseconds const timeout_resolution(50);
|
||||
bool timed_lock_succeeded=rw_mutex.timed_lock(timeout);
|
||||
BOOST_CHECK(boost::get_system_time()<timeout);
|
||||
BOOST_CHECK(timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock();
|
||||
}
|
||||
|
||||
boost::posix_time::milliseconds const wait_duration(500);
|
||||
boost::system_time const timeout2=boost::get_system_time()+wait_duration;
|
||||
timed_lock_succeeded=rw_mutex.timed_lock(wait_duration);
|
||||
BOOST_CHECK(boost::get_system_time()<timeout2);
|
||||
BOOST_CHECK(timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void test_timed_lock_times_out_if_read_lock_held()
|
||||
{
|
||||
boost::shared_mutex rw_mutex;
|
||||
boost::mutex finish_mutex;
|
||||
boost::mutex unblocked_mutex;
|
||||
unsigned unblocked_count=0;
|
||||
boost::mutex::scoped_lock finish_lock(finish_mutex);
|
||||
boost::thread reader(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
|
||||
boost::thread::sleep(delay(1));
|
||||
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
|
||||
|
||||
boost::system_time const start=boost::get_system_time();
|
||||
boost::system_time const timeout=start+boost::posix_time::milliseconds(500);
|
||||
boost::posix_time::milliseconds const timeout_resolution(50);
|
||||
bool timed_lock_succeeded=rw_mutex.timed_lock(timeout);
|
||||
BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock();
|
||||
}
|
||||
|
||||
boost::posix_time::milliseconds const wait_duration(500);
|
||||
boost::system_time const timeout2=boost::get_system_time()+wait_duration;
|
||||
timed_lock_succeeded=rw_mutex.timed_lock(wait_duration);
|
||||
BOOST_CHECK((timeout2-timeout_resolution)<boost::get_system_time());
|
||||
BOOST_CHECK(!timed_lock_succeeded);
|
||||
if(timed_lock_succeeded)
|
||||
{
|
||||
rw_mutex.unlock();
|
||||
}
|
||||
|
||||
finish_lock.unlock();
|
||||
reader.join();
|
||||
}
|
||||
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_no_lock_held));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_shared_succeeds_if_read_lock_held));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_write_lock_held));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_times_out_if_read_lock_held));
|
||||
test->add(BOOST_TEST_CASE(&test_timed_lock_succeeds_if_no_lock_held));
|
||||
|
||||
return test;
|
||||
}
|
||||
Reference in New Issue
Block a user