X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fsessionthread.cpp;h=7df83068ac86dc381f52a1b4e5a8bc6c2021ee0e;hp=7b8bc105655bb9978345c8c22564dbbe816d51bf;hb=ddfb1d2574c4bffd180361a80df9b1cd584bb040;hpb=72473527f99cbe68dcfcb4ca17f828bd3775bba7 diff --git a/src/core/sessionthread.cpp b/src/core/sessionthread.cpp index 7b8bc105..7df83068 100644 --- a/src/core/sessionthread.cpp +++ b/src/core/sessionthread.cpp @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ +#include +#include + #include "core.h" #include "coresession.h" #include "internalpeer.h" @@ -25,107 +28,128 @@ #include "sessionthread.h" #include "signalproxy.h" -SessionThread::SessionThread(UserId uid, bool restoreState, bool strictIdentEnabled, QObject *parent) - : QThread(parent), - _session(0), - _user(uid), - _sessionInitialized(false), - _restoreState(restoreState), - _strictIdentEnabled(strictIdentEnabled) -{ - connect(this, SIGNAL(initialized()), this, SLOT(setSessionInitialized())); -} - +namespace { -SessionThread::~SessionThread() +class Worker : public QObject { - // shut down thread gracefully - quit(); - wait(); -} + 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, SIGNAL(destroyed()), QThread::currentThread(), SLOT(quit())); + connect(_session, SIGNAL(sessionState(Protocol::SessionState)), Core::instance(), SIGNAL(sessionState(Protocol::SessionState))); + emit initialized(); + } -CoreSession *SessionThread::session() -{ - return _session; -} + 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; + } -UserId SessionThread::user() -{ - return _user; -} +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; +}; -bool SessionThread::isSessionInitialized() +} // anon + +SessionThread::SessionThread(UserId uid, bool restoreState, bool strictIdentEnabled, QObject *parent) + : QObject(parent) { - return _sessionInitialized; + auto worker = new Worker(uid, restoreState, strictIdentEnabled); + worker->moveToThread(&_sessionThread); + connect(&_sessionThread, SIGNAL(started()), worker, SLOT(initialize())); + connect(&_sessionThread, SIGNAL(finished()), worker, SLOT(deleteLater())); + connect(worker, SIGNAL(initialized()), this, SLOT(onSessionInitialized())); + connect(worker, SIGNAL(destroyed()), this, SLOT(onSessionDestroyed())); + + connect(this, SIGNAL(addClientToWorker(Peer*)), worker, SLOT(addClient(Peer*))); + connect(this, SIGNAL(shutdownSession()), worker, SLOT(shutdown())); + + // Defer thread start through the event loop, so the SessionThread instance is fully constructed before + QTimer::singleShot(0, &_sessionThread, SLOT(start())); } -void SessionThread::setSessionInitialized() +SessionThread::~SessionThread() { - _sessionInitialized = true; - foreach(QObject *peer, clientQueue) { - addClientToSession(peer); - } - clientQueue.clear(); + // shut down thread gracefully + _sessionThread.quit(); + _sessionThread.wait(30000); } -// this and the following related methods are executed in the Core thread! -void SessionThread::addClient(QObject *peer) +void SessionThread::shutdown() { - if (isSessionInitialized()) { - addClientToSession(peer); - } - else { - clientQueue.append(peer); - } + emit shutdownSession(); } -void SessionThread::addClientToSession(QObject *peer) +void SessionThread::onSessionInitialized() { - RemotePeer *remote = qobject_cast(peer); - if (remote) { - addRemoteClientToSession(remote); - return; - } - - InternalPeer *internal = qobject_cast(peer); - if (internal) { - addInternalClientToSession(internal); - return; + _sessionInitialized = true; + for (auto &&peer : _clientQueue) { + peer->setParent(nullptr); + peer->moveToThread(&_sessionThread); + emit addClientToWorker(peer); } - - qWarning() << "SessionThread::addClient() received invalid peer!" << peer; + _clientQueue.clear(); } -void SessionThread::addRemoteClientToSession(RemotePeer *remotePeer) +void SessionThread::onSessionDestroyed() { - remotePeer->setParent(0); - remotePeer->moveToThread(session()->thread()); - emit addRemoteClient(remotePeer); + emit shutdownComplete(this); } - -void SessionThread::addInternalClientToSession(InternalPeer *internalPeer) +void SessionThread::addClient(Peer *peer) { - internalPeer->setParent(0); - internalPeer->moveToThread(session()->thread()); - emit addInternalClient(internalPeer); + if (_sessionInitialized) { + peer->setParent(nullptr); + peer->moveToThread(&_sessionThread); + emit addClientToWorker(peer); + } + else { + _clientQueue.push_back(peer); + } } - -void SessionThread::run() -{ - _session = new CoreSession(user(), _restoreState, _strictIdentEnabled); - connect(this, SIGNAL(addRemoteClient(RemotePeer*)), _session, SLOT(addClient(RemotePeer*))); - connect(this, SIGNAL(addInternalClient(InternalPeer*)), _session, SLOT(addClient(InternalPeer*))); - connect(_session, SIGNAL(sessionState(Protocol::SessionState)), Core::instance(), SIGNAL(sessionState(Protocol::SessionState))); - emit initialized(); - exec(); - delete _session; -} +#include "sessionthread.moc"