make condition variable c++11 compatible

This commit is contained in:
Arvid Norberg 2013-01-21 22:52:34 +00:00
parent 1b0ddc5560
commit d6fecf4c34
9 changed files with 41 additions and 45 deletions

View File

@ -175,7 +175,7 @@ namespace libtorrent {
std::deque<alert*> m_alerts;
mutable mutex m_mutex;
condition m_condition;
condition_variable m_condition;
boost::uint32_t m_alert_mask;
size_t m_queue_size_limit;
boost::function<void(std::auto_ptr<alert>)> m_dispatch;

View File

@ -521,7 +521,7 @@ namespace libtorrent
// used when posting synchronous function
// calls to session_impl and torrent objects
mutable libtorrent::mutex mut;
mutable libtorrent::condition cond;
mutable libtorrent::condition_variable cond;
void inc_disk_queue(int channel)
{

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_THREAD_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/time.hpp"
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
@ -58,15 +59,13 @@ namespace libtorrent
TORRENT_EXPORT void sleep(int milliseconds);
// TODO: 3 make this interface compatible with c++11
// to allow for smooth transition for platforms with support
struct TORRENT_EXTRA_EXPORT condition
struct TORRENT_EXTRA_EXPORT condition_variable
{
condition();
~condition();
condition_variable();
~condition_variable();
void wait(mutex::scoped_lock& l);
void timed_wait(mutex::scoped_lock& l, int sleep_ms);
void signal_all(mutex::scoped_lock& l);
void wait_for(mutex::scoped_lock& l, time_duration rel_time);
void notify_all();
private:
#ifdef BOOST_HAS_PTHREADS
pthread_cond_t m_cond;

View File

@ -359,7 +359,7 @@ namespace libtorrent {
if (!m_alerts.empty()) return m_alerts.front();
// this call can be interrupted prematurely by other signals
m_condition.timed_wait(lock, total_milliseconds(max_wait));
m_condition.wait_for(lock, max_wait);
if (!m_alerts.empty()) return m_alerts.front();
return NULL;
@ -440,7 +440,7 @@ namespace libtorrent {
{
m_alerts.push_back(alert_.release());
if (m_alerts.size() == 1)
m_condition.signal_all(l);
m_condition.notify_all();
}
}

View File

@ -615,7 +615,7 @@ int feed::next_update(time_t now) const
}
// defined in session.cpp
void fun_wrap(bool* done, condition* e, mutex* m, boost::function<void(void)> f);
void fun_wrap(bool* done, condition_variable* e, mutex* m, boost::function<void(void)> f);
#define TORRENT_ASYNC_CALL(x) \
boost::shared_ptr<feed> f = m_feed_ptr.lock(); \

View File

@ -304,20 +304,20 @@ namespace libtorrent
// wrapper around a function that's executed in the network thread
// ans synchronized in the client thread
template <class R>
void fun_ret(R* ret, bool* done, condition* e, mutex* m, boost::function<R(void)> f)
void fun_ret(R* ret, bool* done, condition_variable* e, mutex* m, boost::function<R(void)> f)
{
*ret = f();
mutex::scoped_lock l(*m);
*done = true;
e->signal_all(l);
e->notify_all();
}
void fun_wrap(bool* done, condition* e, mutex* m, boost::function<void(void)> f)
void fun_wrap(bool* done, condition_variable* e, mutex* m, boost::function<void(void)> f)
{
f();
mutex::scoped_lock l(*m);
*done = true;
e->signal_all(l);
e->notify_all();
}
#define TORRENT_ASYNC_CALL(x) \

View File

@ -57,56 +57,55 @@ namespace libtorrent
#ifdef BOOST_HAS_PTHREADS
condition::condition()
condition_variable::condition_variable()
{
pthread_cond_init(&m_cond, 0);
}
condition::~condition()
condition_variable::~condition_variable()
{
pthread_cond_destroy(&m_cond);
}
void condition::wait(mutex::scoped_lock& l)
void condition_variable::wait(mutex::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
// wow, this is quite a hack
pthread_cond_wait(&m_cond, (::pthread_mutex_t*)&l.mutex());
}
void condition::timed_wait(mutex::scoped_lock& l, int sleep_ms)
void condition_variable::wait_for(mutex::scoped_lock& l, time_duration rel_time)
{
TORRENT_ASSERT(l.locked());
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, NULL);
boost::uint64_t microseconds = tv.tv_usec + boost::uint64_t(sleep_ms % 1000) * 1000;
boost::uint64_t microseconds = tv.tv_usec + total_microseconds(rel_time) % 1000000;
ts.tv_nsec = (microseconds % 1000000) * 1000;
ts.tv_sec = tv.tv_sec + sleep_ms / 1000 + microseconds / 1000000;
ts.tv_sec = tv.tv_sec + total_seconds(rel_time) + microseconds / 1000000;
// wow, this is quite a hack
pthread_cond_timedwait(&m_cond, (::pthread_mutex_t*)&l.mutex(), &ts);
}
void condition::signal_all(mutex::scoped_lock& l)
void condition_variable::notify_all()
{
TORRENT_ASSERT(l.locked());
pthread_cond_broadcast(&m_cond);
}
#elif defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
condition::condition()
condition_variable::condition_variable()
: m_num_waiters(0)
{
m_sem = CreateSemaphore(0, 0, INT_MAX, 0);
}
condition::~condition()
condition_variable::~condition_variable()
{
CloseHandle(m_sem);
}
void condition::wait(mutex::scoped_lock& l)
void condition_variable::wait(mutex::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
++m_num_waiters;
@ -116,34 +115,33 @@ namespace libtorrent
--m_num_waiters;
}
void condition::timed_wait(mutex::scoped_lock& l, int sleep_ms)
void condition_variable::wait_for(mutex::scoped_lock& l, time_duration rel_time)
{
TORRENT_ASSERT(l.locked());
++m_num_waiters;
l.unlock();
WaitForSingleObject(m_sem, sleep_ms);
WaitForSingleObject(m_sem, total_milliseconds(rel_time));
l.lock();
--m_num_waiters;
}
void condition::signal_all(mutex::scoped_lock& l)
void condition_variable::notify_all()
{
TORRENT_ASSERT(l.locked());
ReleaseSemaphore(m_sem, m_num_waiters, 0);
}
#elif defined TORRENT_BEOS
condition::condition()
condition_variable::condition_variable()
: m_num_waiters(0)
{
m_sem = create_sem(0, 0);
}
condition::~condition()
condition_variable::~condition_variable()
{
delete_sem(m_sem);
}
void condition::wait(mutex::scoped_lock& l)
void condition_variable::wait(mutex::scoped_lock& l)
{
TORRENT_ASSERT(l.locked());
++m_num_waiters;
@ -153,19 +151,18 @@ namespace libtorrent
--m_num_waiters;
}
void condition::timed_wait(mutex::scoped_lock& l, int sleep_ms)
void condition_variable::wait_for(mutex::scoped_lock& l, time_duration rel_time)
{
TORRENT_ASSERT(l.locked());
++m_num_waiters;
l.unlock();
acquire_sem_etc(m_sem, 1, B_RELATIVE_TIMEOUT, bigtime_t(sleep_ms) * 1000);
acquire_sem_etc(m_sem, 1, B_RELATIVE_TIMEOUT, total_microseconds(rel_time));
l.lock();
--m_num_waiters;
}
void condition::signal_all(mutex::scoped_lock& l)
void condition_variable::notify_all()
{
TORRENT_ASSERT(l.locked());
release_sem_etc(m_sem, m_num_waiters, 0);
}
#else

View File

@ -147,16 +147,16 @@ namespace libtorrent
torrent_status::~torrent_status() {}
template <class R>
void fun_ret(R* ret, bool* done, condition* e, mutex* m, boost::function<R(void)> f)
void fun_ret(R* ret, bool* done, condition_variable* e, mutex* m, boost::function<R(void)> f)
{
*ret = f();
mutex::scoped_lock l(*m);
*done = true;
e->signal_all(l);
e->notify_all();
}
// defined in session.cpp
void fun_wrap(bool* done, condition* e, mutex* m, boost::function<void(void)> f);
void fun_wrap(bool* done, condition_variable* e, mutex* m, boost::function<void(void)> f);
#define TORRENT_ASYNC_CALL(x) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \

View File

@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
using namespace libtorrent;
void fun(condition* s, libtorrent::mutex* m, int i)
void fun(condition_variable* s, libtorrent::mutex* m, int i)
{
fprintf(stderr, "thread %d waiting\n", i);
libtorrent::mutex::scoped_lock l(*m);
@ -47,7 +47,7 @@ void fun(condition* s, libtorrent::mutex* m, int i)
int test_main()
{
condition cond;
condition_variable cond;
libtorrent::mutex m;
std::list<thread*> threads;
for (int i = 0; i < 20; ++i)
@ -55,11 +55,11 @@ int test_main()
threads.push_back(new thread(boost::bind(&fun, &cond, &m, i)));
}
// make sure all threads are waiting on the condition
// make sure all threads are waiting on the condition_variable
sleep(10);
libtorrent::mutex::scoped_lock l(m);
cond.signal_all(l);
cond.notify_all();
l.unlock();
for (std::list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i)