clazy: Convert many old-style connects into function pointer based
[quassel.git] / src / core / sessionthread.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include <QPointer>
22 #include <QTimer>
23
24 #include "core.h"
25 #include "coresession.h"
26 #include "internalpeer.h"
27 #include "remotepeer.h"
28 #include "sessionthread.h"
29 #include "signalproxy.h"
30
31 namespace {
32
33 class Worker : public QObject
34 {
35     Q_OBJECT
36
37 public:
38     Worker(UserId userId, bool restoreState, bool strictIdentEnabled)
39         : _userId{userId}
40         , _restoreState{restoreState}
41         , _strictIdentEnabled{strictIdentEnabled}
42     {
43     }
44
45 public slots:
46     void initialize()
47     {
48         _session = new CoreSession{_userId, _restoreState, _strictIdentEnabled, this};
49         connect(_session, &QObject::destroyed, QThread::currentThread(), &QThread::quit);
50         connect(_session, SIGNAL(sessionState(Protocol::SessionState)), Core::instance(), SIGNAL(sessionState(Protocol::SessionState)));
51         emit initialized();
52     }
53
54     void shutdown()
55     {
56         if (_session) {
57             _session->shutdown();
58         }
59     }
60
61     void addClient(Peer *peer)
62     {
63         if (!_session) {
64             qWarning() << "Session not initialized!";
65             return;
66         }
67
68         auto remotePeer = qobject_cast<RemotePeer*>(peer);
69         if (remotePeer) {
70             _session->addClient(remotePeer);
71             return;
72         }
73         auto internalPeer = qobject_cast<InternalPeer*>(peer);
74         if (internalPeer) {
75             _session->addClient(internalPeer);
76             return;
77         }
78
79         qWarning() << "SessionThread::addClient() received invalid peer!" << peer;
80     }
81
82 signals:
83     void initialized();
84
85 private:
86     UserId _userId;
87     bool _restoreState;
88     bool _strictIdentEnabled;  ///< Whether or not strict ident mode is enabled, locking users' idents to Quassel username
89     QPointer<CoreSession> _session;
90 };
91
92 }  // anon
93
94 SessionThread::SessionThread(UserId uid, bool restoreState, bool strictIdentEnabled, QObject *parent)
95     : QObject(parent)
96 {
97     auto worker = new Worker(uid, restoreState, strictIdentEnabled);
98     worker->moveToThread(&_sessionThread);
99     connect(&_sessionThread, &QThread::started, worker, &Worker::initialize);
100     connect(&_sessionThread, &QThread::finished, worker, &QObject::deleteLater);
101     connect(worker, &Worker::initialized, this, &SessionThread::onSessionInitialized);
102     connect(worker, &QObject::destroyed, this, &SessionThread::onSessionDestroyed);
103
104     connect(this, &SessionThread::addClientToWorker, worker, &Worker::addClient);
105     connect(this, &SessionThread::shutdownSession, worker, &Worker::shutdown);
106
107     // Defer thread start through the event loop, so the SessionThread instance is fully constructed before
108     QTimer::singleShot(0, &_sessionThread, SLOT(start()));
109 }
110
111
112 SessionThread::~SessionThread()
113 {
114     // shut down thread gracefully
115     _sessionThread.quit();
116     _sessionThread.wait(30000);
117 }
118
119
120 void SessionThread::shutdown()
121 {
122     emit shutdownSession();
123 }
124
125
126 void SessionThread::onSessionInitialized()
127 {
128     _sessionInitialized = true;
129     for (auto &&peer : _clientQueue) {
130         peer->setParent(nullptr);
131         peer->moveToThread(&_sessionThread);
132         emit addClientToWorker(peer);
133     }
134     _clientQueue.clear();
135 }
136
137
138 void SessionThread::onSessionDestroyed()
139 {
140     emit shutdownComplete(this);
141 }
142
143 void SessionThread::addClient(Peer *peer)
144 {
145     if (_sessionInitialized) {
146         peer->setParent(nullptr);
147         peer->moveToThread(&_sessionThread);
148         emit addClientToWorker(peer);
149     }
150     else {
151         _clientQueue.push_back(peer);
152     }
153 }
154
155 #include "sessionthread.moc"