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; std::deque<alert*> m_alerts;
mutable mutex m_mutex; mutable mutex m_mutex;
condition m_condition; condition_variable m_condition;
boost::uint32_t m_alert_mask; boost::uint32_t m_alert_mask;
size_t m_queue_size_limit; size_t m_queue_size_limit;
boost::function<void(std::auto_ptr<alert>)> m_dispatch; boost::function<void(std::auto_ptr<alert>)> m_dispatch;

View File

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

View File

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

View File

@ -359,7 +359,7 @@ namespace libtorrent {
if (!m_alerts.empty()) return m_alerts.front(); if (!m_alerts.empty()) return m_alerts.front();
// this call can be interrupted prematurely by other signals // 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(); if (!m_alerts.empty()) return m_alerts.front();
return NULL; return NULL;
@ -440,7 +440,7 @@ namespace libtorrent {
{ {
m_alerts.push_back(alert_.release()); m_alerts.push_back(alert_.release());
if (m_alerts.size() == 1) 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 // 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) \ #define TORRENT_ASYNC_CALL(x) \
boost::shared_ptr<feed> f = m_feed_ptr.lock(); \ 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 // wrapper around a function that's executed in the network thread
// ans synchronized in the client thread // ans synchronized in the client thread
template <class R> 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(); *ret = f();
mutex::scoped_lock l(*m); mutex::scoped_lock l(*m);
*done = true; *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(); f();
mutex::scoped_lock l(*m); mutex::scoped_lock l(*m);
*done = true; *done = true;
e->signal_all(l); e->notify_all();
} }
#define TORRENT_ASYNC_CALL(x) \ #define TORRENT_ASYNC_CALL(x) \

View File

@ -57,56 +57,55 @@ namespace libtorrent
#ifdef BOOST_HAS_PTHREADS #ifdef BOOST_HAS_PTHREADS
condition::condition() condition_variable::condition_variable()
{ {
pthread_cond_init(&m_cond, 0); pthread_cond_init(&m_cond, 0);
} }
condition::~condition() condition_variable::~condition_variable()
{ {
pthread_cond_destroy(&m_cond); pthread_cond_destroy(&m_cond);
} }
void condition::wait(mutex::scoped_lock& l) void condition_variable::wait(mutex::scoped_lock& l)
{ {
TORRENT_ASSERT(l.locked()); TORRENT_ASSERT(l.locked());
// wow, this is quite a hack // wow, this is quite a hack
pthread_cond_wait(&m_cond, (::pthread_mutex_t*)&l.mutex()); 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()); TORRENT_ASSERT(l.locked());
struct timeval tv; struct timeval tv;
struct timespec ts; struct timespec ts;
gettimeofday(&tv, NULL); 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_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 // wow, this is quite a hack
pthread_cond_timedwait(&m_cond, (::pthread_mutex_t*)&l.mutex(), &ts); 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); pthread_cond_broadcast(&m_cond);
} }
#elif defined TORRENT_WINDOWS || defined TORRENT_CYGWIN #elif defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
condition::condition() condition_variable::condition_variable()
: m_num_waiters(0) : m_num_waiters(0)
{ {
m_sem = CreateSemaphore(0, 0, INT_MAX, 0); m_sem = CreateSemaphore(0, 0, INT_MAX, 0);
} }
condition::~condition() condition_variable::~condition_variable()
{ {
CloseHandle(m_sem); CloseHandle(m_sem);
} }
void condition::wait(mutex::scoped_lock& l) void condition_variable::wait(mutex::scoped_lock& l)
{ {
TORRENT_ASSERT(l.locked()); TORRENT_ASSERT(l.locked());
++m_num_waiters; ++m_num_waiters;
@ -116,34 +115,33 @@ namespace libtorrent
--m_num_waiters; --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()); TORRENT_ASSERT(l.locked());
++m_num_waiters; ++m_num_waiters;
l.unlock(); l.unlock();
WaitForSingleObject(m_sem, sleep_ms); WaitForSingleObject(m_sem, total_milliseconds(rel_time));
l.lock(); l.lock();
--m_num_waiters; --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); ReleaseSemaphore(m_sem, m_num_waiters, 0);
} }
#elif defined TORRENT_BEOS #elif defined TORRENT_BEOS
condition::condition() condition_variable::condition_variable()
: m_num_waiters(0) : m_num_waiters(0)
{ {
m_sem = create_sem(0, 0); m_sem = create_sem(0, 0);
} }
condition::~condition() condition_variable::~condition_variable()
{ {
delete_sem(m_sem); delete_sem(m_sem);
} }
void condition::wait(mutex::scoped_lock& l) void condition_variable::wait(mutex::scoped_lock& l)
{ {
TORRENT_ASSERT(l.locked()); TORRENT_ASSERT(l.locked());
++m_num_waiters; ++m_num_waiters;
@ -153,19 +151,18 @@ namespace libtorrent
--m_num_waiters; --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()); TORRENT_ASSERT(l.locked());
++m_num_waiters; ++m_num_waiters;
l.unlock(); 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(); l.lock();
--m_num_waiters; --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); release_sem_etc(m_sem, m_num_waiters, 0);
} }
#else #else

View File

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

View File

@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
using namespace libtorrent; 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); fprintf(stderr, "thread %d waiting\n", i);
libtorrent::mutex::scoped_lock l(*m); libtorrent::mutex::scoped_lock l(*m);
@ -47,7 +47,7 @@ void fun(condition* s, libtorrent::mutex* m, int i)
int test_main() int test_main()
{ {
condition cond; condition_variable cond;
libtorrent::mutex m; libtorrent::mutex m;
std::list<thread*> threads; std::list<thread*> threads;
for (int i = 0; i < 20; ++i) 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))); 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); sleep(10);
libtorrent::mutex::scoped_lock l(m); libtorrent::mutex::scoped_lock l(m);
cond.signal_all(l); cond.notify_all();
l.unlock(); l.unlock();
for (std::list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i) for (std::list<thread*>::iterator i = threads.begin(); i != threads.end(); ++i)