X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fsessionthread.cpp;h=bdc0a7388d1fcd46dd99db105d2b76db7e54ec5d;hp=35caf13be27eef07c065e252a16b97219d5e8421;hb=fcacaaf16551524c7ebb6114254d005274cc3d63;hpb=c91b08f855152297a89ec3586792f6616acd0eb9 diff --git a/src/core/sessionthread.cpp b/src/core/sessionthread.cpp index 35caf13b..bdc0a738 100644 --- a/src/core/sessionthread.cpp +++ b/src/core/sessionthread.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-09 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -15,93 +15,141 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#include +#include +#include +#include "core.h" +#include "coresession.h" +#include "internalpeer.h" +#include "remotepeer.h" #include "sessionthread.h" #include "signalproxy.h" -#include "coresession.h" -#include "core.h" -SessionThread::SessionThread(UserId uid, bool restoreState, QObject *parent) - : QThread(parent), - _session(0), - _user(uid), - _sessionInitialized(false), - _restoreState(restoreState) -{ - connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized())); -} +namespace { -SessionThread::~SessionThread() { - // shut down thread gracefully - quit(); - wait(); +class Worker : public QObject +{ + Q_OBJECT + +public: + Worker(UserId userId, bool restoreState, bool strictIdentEnabled) + : _userId{userId} + , _restoreState{restoreState} + , _strictIdentEnabled{strictIdentEnabled} + { + } + +public slots: + void initialize() + { + _session = new CoreSession{_userId, _restoreState, _strictIdentEnabled, this}; + connect(_session, &QObject::destroyed, QThread::currentThread(), &QThread::quit); + connect(_session, SIGNAL(sessionState(Protocol::SessionState)), Core::instance(), SIGNAL(sessionState(Protocol::SessionState))); + emit initialized(); + } + + void shutdown() + { + if (_session) { + _session->shutdown(); + } + } + + void addClient(Peer *peer) + { + if (!_session) { + qWarning() << "Session not initialized!"; + return; + } + + auto remotePeer = qobject_cast(peer); + if (remotePeer) { + _session->addClient(remotePeer); + return; + } + auto internalPeer = qobject_cast(peer); + if (internalPeer) { + _session->addClient(internalPeer); + return; + } + + qWarning() << "SessionThread::addClient() received invalid peer!" << peer; + } + +signals: + void initialized(); + +private: + UserId _userId; + bool _restoreState; + bool _strictIdentEnabled; ///< Whether or not strict ident mode is enabled, locking users' idents to Quassel username + QPointer _session; +}; + +} // anon + +SessionThread::SessionThread(UserId uid, bool restoreState, bool strictIdentEnabled, QObject *parent) + : QObject(parent) +{ + auto worker = new Worker(uid, restoreState, strictIdentEnabled); + worker->moveToThread(&_sessionThread); + connect(&_sessionThread, &QThread::started, worker, &Worker::initialize); + connect(&_sessionThread, &QThread::finished, worker, &QObject::deleteLater); + connect(worker, &Worker::initialized, this, &SessionThread::onSessionInitialized); + connect(worker, &QObject::destroyed, this, &SessionThread::onSessionDestroyed); + + connect(this, &SessionThread::addClientToWorker, worker, &Worker::addClient); + connect(this, &SessionThread::shutdownSession, worker, &Worker::shutdown); + + // Defer thread start through the event loop, so the SessionThread instance is fully constructed before + QTimer::singleShot(0, &_sessionThread, SLOT(start())); } -CoreSession *SessionThread::session() { - return _session; -} -UserId SessionThread::user() { - return _user; -} - -bool SessionThread::isSessionInitialized() { - return _sessionInitialized; +SessionThread::~SessionThread() +{ + // shut down thread gracefully + _sessionThread.quit(); + _sessionThread.wait(30000); } -void SessionThread::setSessionInitialized() { - _sessionInitialized = true; - foreach(QObject *peer, clientQueue) { - addClientToSession(peer); - } - clientQueue.clear(); -} -void SessionThread::addClient(QObject *peer) { - if(isSessionInitialized()) { - addClientToSession(peer); - } else { - clientQueue.append(peer); - } +void SessionThread::shutdown() +{ + emit shutdownSession(); } -void SessionThread::addClientToSession(QObject *peer) { - QIODevice *socket = qobject_cast(peer); - if(socket) { - addRemoteClientToSession(socket); - return; - } - - SignalProxy *proxy = qobject_cast(peer); - if(proxy) { - addInternalClientToSession(proxy); - return; - } - qWarning() << "SessionThread::addClient() received neither QIODevice nor SignalProxy as peer!" << peer; +void SessionThread::onSessionInitialized() +{ + _sessionInitialized = true; + for (auto &&peer : _clientQueue) { + peer->setParent(nullptr); + peer->moveToThread(&_sessionThread); + emit addClientToWorker(peer); + } + _clientQueue.clear(); } -void SessionThread::addRemoteClientToSession(QIODevice *socket) { - socket->setParent(0); - socket->moveToThread(session()->thread()); - emit addRemoteClient(socket); -} -void SessionThread::addInternalClientToSession(SignalProxy *proxy) { - emit addInternalClient(proxy); +void SessionThread::onSessionDestroyed() +{ + emit shutdownComplete(this); } -void SessionThread::run() { - _session = new CoreSession(user(), _restoreState); - connect(this, SIGNAL(addRemoteClient(QIODevice *)), _session, SLOT(addClient(QIODevice *))); - connect(this, SIGNAL(addInternalClient(SignalProxy *)), _session, SLOT(addClient(SignalProxy *))); - connect(_session, SIGNAL(sessionState(const QVariant &)), Core::instance(), SIGNAL(sessionState(const QVariant &))); - emit initialized(); - exec(); - delete _session; +void SessionThread::addClient(Peer *peer) +{ + if (_sessionInitialized) { + peer->setParent(nullptr); + peer->moveToThread(&_sessionThread); + emit addClientToWorker(peer); + } + else { + _clientQueue.push_back(peer); + } } +#include "sessionthread.moc"