2014-05-17 13:04:33 +04:00
|
|
|
#include "alertdispatcher.h"
|
|
|
|
|
|
|
|
#include <boost/bind.hpp>
|
|
|
|
#include <QMutexLocker>
|
|
|
|
|
|
|
|
QAlertDispatcher::QAlertDispatcher(libtorrent::session *session, QObject* parent)
|
|
|
|
: QObject(parent)
|
2014-06-03 20:35:50 +03:00
|
|
|
, m_session(session)
|
2014-05-17 13:04:33 +04:00
|
|
|
, current_tag(new QAtomicPointer<QAlertDispatcher>(this))
|
2014-06-03 20:35:50 +03:00
|
|
|
, event_posted(false)
|
|
|
|
{
|
|
|
|
m_session->set_alert_dispatch(boost::bind(&QAlertDispatcher::dispatch, current_tag, _1));
|
2014-05-17 13:04:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
QAlertDispatcher::~QAlertDispatcher() {
|
|
|
|
// When QAlertDispatcher is destoyed, libtorrent still can call
|
|
|
|
// QAlertDispatcher::dispatch a few times after destruction. This is
|
|
|
|
// handled by passing a "tag". A tag is a object that references QAlertDispatch.
|
|
|
|
// Tag could be invalidated. So on destruction QAlertDispatcher invalidates a tag
|
|
|
|
// and then unsubscribes from alerts. When QAlertDispatcher::dispatch is called
|
|
|
|
// with invalid tag it simply discard an alert.
|
|
|
|
|
|
|
|
{
|
2014-06-03 20:35:50 +03:00
|
|
|
QMutexLocker lock(&alerts_mutex);
|
2014-05-17 13:04:33 +04:00
|
|
|
*current_tag = 0;
|
|
|
|
current_tag.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef boost::function<void (std::auto_ptr<libtorrent::alert>)> dispatch_function_t;
|
2014-06-03 20:35:50 +03:00
|
|
|
m_session->set_alert_dispatch(dispatch_function_t());
|
2014-05-17 13:04:33 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void QAlertDispatcher::getPendingAlertsNoWait(std::deque<libtorrent::alert*>& out) {
|
|
|
|
Q_ASSERT(out.empty());
|
|
|
|
|
2014-06-03 20:35:50 +03:00
|
|
|
QMutexLocker lock(&alerts_mutex);
|
|
|
|
alerts.swap(out);
|
2014-05-17 13:04:33 +04:00
|
|
|
event_posted = false;
|
|
|
|
}
|
|
|
|
|
2014-06-03 20:35:50 +03:00
|
|
|
void QAlertDispatcher::getPendingAlerts(std::deque<libtorrent::alert*>& out, unsigned long time) {
|
|
|
|
Q_ASSERT(out.empty());
|
2014-05-17 13:04:33 +04:00
|
|
|
|
2014-06-03 20:35:50 +03:00
|
|
|
QMutexLocker lock(&alerts_mutex);
|
2014-05-17 13:04:33 +04:00
|
|
|
|
|
|
|
while (alerts.empty())
|
2014-06-03 20:35:50 +03:00
|
|
|
alerts_condvar.wait(&alerts_mutex, time);
|
2014-05-17 13:04:33 +04:00
|
|
|
|
2014-06-03 20:35:50 +03:00
|
|
|
alerts.swap(out);
|
2014-05-17 13:04:33 +04:00
|
|
|
event_posted = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void QAlertDispatcher::dispatch(QSharedPointer<QAtomicPointer<QAlertDispatcher> > tag,
|
|
|
|
std::auto_ptr<libtorrent::alert> alert_ptr) {
|
|
|
|
QAlertDispatcher* that = *tag;
|
|
|
|
if (!that)
|
|
|
|
return;
|
|
|
|
|
|
|
|
QMutexLocker lock(&(that->alerts_mutex));
|
|
|
|
|
2014-06-03 20:35:50 +03:00
|
|
|
if (!*tag)
|
2014-05-17 13:04:33 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
bool was_empty = that->alerts.empty();
|
|
|
|
|
|
|
|
that->alerts.push_back(alert_ptr.get());
|
|
|
|
alert_ptr.release();
|
|
|
|
|
|
|
|
if (was_empty)
|
|
|
|
that->alerts_condvar.wakeAll();
|
|
|
|
|
|
|
|
that->enqueueToMainThread();
|
|
|
|
|
|
|
|
Q_ASSERT(that->current_tag == tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QAlertDispatcher::enqueueToMainThread() {
|
|
|
|
if (!event_posted) {
|
|
|
|
event_posted = true;
|
|
|
|
QMetaObject::invokeMethod(this, "deliverSignal", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QAlertDispatcher::deliverSignal() {
|
|
|
|
emit alertsReceived();
|
|
|
|
|
2014-06-03 20:35:50 +03:00
|
|
|
QMutexLocker lock(&alerts_mutex);
|
2014-05-17 13:04:33 +04:00
|
|
|
event_posted = false;
|
|
|
|
|
|
|
|
if (!alerts.empty())
|
|
|
|
enqueueToMainThread();
|
|
|
|
}
|