Skip to content

Commit 7df9788

Browse files
laanwjknst
authored andcommitted
Merge bitcoin-core/gui#381: refactor: Make BitcoinCore class reusable
8169fc4 qt, refactor: Fix code styling of moved InitExecutor class (Hennadii Stepanov) c82165a qt, refactor: Move InitExecutor class into its own module (Hennadii Stepanov) dbcf56b scripted-diff: Rename BitcoinCore class to InitExecutor (Hennadii Stepanov) 19a1d00 qt: Add BitcoinCore::m_thread member (Hennadii Stepanov) Pull request description: This PR makes the `BitcoinCore` class reusable, i.e., it can be used by the widget-based GUI or by the [QML-based](https://github.com/bitcoin-core/gui-qml/tree/main/src/qml) one, and it makes the divergence between these two repos minimal. The small benefit to the current branch is more structured code. Actually, this PR is ported from bitcoin-core/gui-qml#10. The example of the re-using of the `BitcoinCore` class is bitcoin-core/gui-qml#11. ACKs for top commit: laanwj: ACK 8169fc4 ryanofsky: Code review ACK 8169fc4. Only change is switching from `m_executor` from pointer to optional type (thanks for update!) Tree-SHA512: a0552c32d26d9acf42921eb12bcdf68f02d52f7183c688c43257b1a58679f64e45f193ee2d316850c7f0f516561e17abe989fe545bfa05e158ad3f4c66d19bca
1 parent 40a8b92 commit 7df9788

6 files changed

+166
-129
lines changed

src/Makefile.qt.include

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ QT_MOC_CPP = \
5858
qt/moc_editaddressdialog.cpp \
5959
qt/moc_governancelist.cpp \
6060
qt/moc_guiutil.cpp \
61+
qt/moc_initexecutor.cpp \
6162
qt/moc_intro.cpp \
6263
qt/moc_macdockiconhandler.cpp \
6364
qt/moc_macnotificationhandler.cpp \
@@ -133,6 +134,7 @@ BITCOIN_QT_H = \
133134
qt/governancelist.h \
134135
qt/guiconstants.h \
135136
qt/guiutil.h \
137+
qt/initexecutor.h \
136138
qt/intro.h \
137139
qt/macdockiconhandler.h \
138140
qt/macnotificationhandler.h \
@@ -222,6 +224,7 @@ BITCOIN_QT_BASE_CPP = \
222224
qt/clientmodel.cpp \
223225
qt/csvmodelwriter.cpp \
224226
qt/guiutil.cpp \
227+
qt/initexecutor.cpp \
225228
qt/intro.cpp \
226229
qt/modaloverlay.cpp \
227230
qt/networkstyle.cpp \

src/qt/bitcoin.cpp

+24-100
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,41 @@
88
#endif
99

1010
#include <qt/bitcoin.h>
11-
#include <qt/bitcoingui.h>
1211

1312
#include <chainparams.h>
1413
#include <fs.h>
14+
#include <init.h>
15+
#include <interfaces/handler.h>
16+
#include <interfaces/node.h>
17+
#include <net.h>
18+
#include <node/context.h>
19+
#include <node/ui_interface.h>
20+
#include <noui.h>
21+
#include <qt/bitcoingui.h>
1522
#include <qt/clientmodel.h>
1623
#include <qt/guiconstants.h>
1724
#include <qt/guiutil.h>
25+
#include <qt/initexecutor.h>
1826
#include <qt/intro.h>
19-
#include <net.h>
2027
#include <qt/networkstyle.h>
2128
#include <qt/optionsmodel.h>
2229
#include <qt/splashscreen.h>
2330
#include <qt/utilitydialog.h>
2431
#include <qt/winshutdownmonitor.h>
32+
#include <stacktraces.h>
33+
#include <uint256.h>
2534
#include <util/string.h>
35+
#include <util/system.h>
36+
#include <util/threadnames.h>
37+
#include <util/translation.h>
38+
#include <validation.h>
2639

2740
#ifdef ENABLE_WALLET
2841
#include <qt/paymentserver.h>
2942
#include <qt/walletcontroller.h>
3043
#include <qt/walletmodel.h>
3144
#endif // ENABLE_WALLET
3245

33-
#include <init.h>
34-
#include <interfaces/handler.h>
35-
#include <interfaces/node.h>
36-
#include <node/context.h>
37-
#include <node/ui_interface.h>
38-
#include <noui.h>
39-
#include <stacktraces.h>
40-
#include <uint256.h>
41-
#include <util/system.h>
42-
#include <util/threadnames.h>
43-
#include <util/translation.h>
44-
#include <validation.h>
45-
4646
#include <boost/signals2/connection.hpp>
4747
#include <memory>
4848

@@ -52,7 +52,6 @@
5252
#include <QLibraryInfo>
5353
#include <QLocale>
5454
#include <QMessageBox>
55-
#include <QProcess>
5655
#include <QSettings>
5756
#include <QThread>
5857
#include <QTimer>
@@ -208,72 +207,11 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
208207
}
209208
}
210209

211-
BitcoinCore::BitcoinCore(interfaces::Node& node) :
212-
QObject(), m_node(node)
213-
{
214-
}
215-
216-
void BitcoinCore::handleRunawayException(const std::exception_ptr e)
217-
{
218-
PrintExceptionContinue(e, "Runaway exception");
219-
Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings().translated));
220-
}
221-
222-
void BitcoinCore::initialize()
223-
{
224-
try
225-
{
226-
util::ThreadRename("qt-init");
227-
qDebug() << __func__ << ": Running initialization in thread";
228-
interfaces::BlockAndHeaderTipInfo tip_info;
229-
bool rv = m_node.appInitMain(&tip_info);
230-
Q_EMIT initializeResult(rv, tip_info);
231-
} catch (...) {
232-
handleRunawayException(std::current_exception());
233-
}
234-
}
235-
236-
void BitcoinCore::restart(QStringList args)
237-
{
238-
static bool executing_restart{false};
239-
240-
if(!executing_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
241-
executing_restart = true;
242-
try
243-
{
244-
qDebug() << __func__ << ": Running Restart in thread";
245-
m_node.appPrepareShutdown();
246-
qDebug() << __func__ << ": Shutdown finished";
247-
Q_EMIT shutdownResult();
248-
CExplicitNetCleanup::callCleanup();
249-
QProcess::startDetached(QApplication::applicationFilePath(), args);
250-
qDebug() << __func__ << ": Restart initiated...";
251-
QApplication::quit();
252-
} catch (...) {
253-
handleRunawayException(std::current_exception());
254-
}
255-
}
256-
}
257-
258-
void BitcoinCore::shutdown()
259-
{
260-
try
261-
{
262-
qDebug() << __func__ << ": Running Shutdown in thread";
263-
m_node.appShutdown();
264-
qDebug() << __func__ << ": Shutdown finished";
265-
Q_EMIT shutdownResult();
266-
} catch (...) {
267-
handleRunawayException(std::current_exception());
268-
}
269-
}
270-
271210
static int qt_argc = 1;
272211
static const char* qt_argv = "dash-qt";
273212

274213
BitcoinApplication::BitcoinApplication():
275214
QApplication(qt_argc, const_cast<char **>(&qt_argv)),
276-
coreThread(nullptr),
277215
optionsModel(nullptr),
278216
clientModel(nullptr),
279217
window(nullptr),
@@ -287,13 +225,7 @@ BitcoinApplication::BitcoinApplication():
287225

288226
BitcoinApplication::~BitcoinApplication()
289227
{
290-
if(coreThread)
291-
{
292-
qDebug() << __func__ << ": Stopping thread";
293-
coreThread->quit();
294-
coreThread->wait();
295-
qDebug() << __func__ << ": Stopped thread";
296-
}
228+
m_executor.reset();
297229

298230
delete window;
299231
window = nullptr;
@@ -350,23 +282,16 @@ bool BitcoinApplication::baseInitialize()
350282

351283
void BitcoinApplication::startThread()
352284
{
353-
if(coreThread)
354-
return;
355-
coreThread = new QThread(this);
356-
BitcoinCore *executor = new BitcoinCore(node());
357-
executor->moveToThread(coreThread);
285+
assert(!m_executor);
286+
m_executor.emplace(node());
358287

359288
/* communication to and from thread */
360-
connect(executor, &BitcoinCore::initializeResult, this, &BitcoinApplication::initializeResult);
361-
connect(executor, &BitcoinCore::shutdownResult, this, &BitcoinApplication::shutdownResult);
362-
connect(executor, &BitcoinCore::runawayException, this, &BitcoinApplication::handleRunawayException);
363-
connect(this, &BitcoinApplication::requestedInitialize, executor, &BitcoinCore::initialize);
364-
connect(this, &BitcoinApplication::requestedShutdown, executor, &BitcoinCore::shutdown);
365-
connect(window, &BitcoinGUI::requestedRestart, executor, &BitcoinCore::restart);
366-
/* make sure executor object is deleted in its own thread */
367-
connect(coreThread, &QThread::finished, executor, &QObject::deleteLater);
368-
369-
coreThread->start();
289+
connect(&m_executor.value(), &InitExecutor::initializeResult, this, &BitcoinApplication::initializeResult);
290+
connect(&m_executor.value(), &InitExecutor::shutdownResult, this, &BitcoinApplication::shutdownResult);
291+
connect(&m_executor.value(), &InitExecutor::runawayException, this, &BitcoinApplication::handleRunawayException);
292+
connect(this, &BitcoinApplication::requestedInitialize, &m_executor.value(), &InitExecutor::initialize);
293+
connect(this, &BitcoinApplication::requestedShutdown, &m_executor.value(), &InitExecutor::shutdown);
294+
connect(window, &BitcoinGUI::requestedRestart, &m_executor.value(), &InitExecutor::restart);
370295
}
371296

372297
void BitcoinApplication::parameterSetup()
@@ -399,7 +324,6 @@ void BitcoinApplication::requestShutdown()
399324
shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window));
400325

401326
qDebug() << __func__ << ": Requesting shutdown";
402-
startThread();
403327
window->hide();
404328
// Must disconnect node signals otherwise current thread can deadlock since
405329
// no event loop is running.

src/qt/bitcoin.h

+6-29
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
#include <config/bitcoin-config.h>
1010
#endif
1111

12-
#include <QApplication>
12+
#include <interfaces/node.h>
13+
#include <qt/initexecutor.h>
14+
1315
#include <assert.h>
1416
#include <memory>
17+
#include <optional>
1518

16-
#include <interfaces/node.h>
19+
#include <QApplication>
1720

1821
class BitcoinGUI;
1922
class ClientModel;
@@ -25,32 +28,6 @@ class WalletController;
2528
class WalletModel;
2629

2730

28-
/** Class encapsulating Bitcoin Core startup and shutdown.
29-
* Allows running startup and shutdown in a different thread from the UI thread.
30-
*/
31-
class BitcoinCore: public QObject
32-
{
33-
Q_OBJECT
34-
public:
35-
explicit BitcoinCore(interfaces::Node& node);
36-
37-
public Q_SLOTS:
38-
void initialize();
39-
void shutdown();
40-
void restart(QStringList args);
41-
42-
Q_SIGNALS:
43-
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info);
44-
void shutdownResult();
45-
void runawayException(const QString &message);
46-
47-
private:
48-
/// Pass fatal exception message to UI thread
49-
void handleRunawayException(const std::exception_ptr e);
50-
51-
interfaces::Node& m_node;
52-
};
53-
5431
/** Main Bitcoin application object */
5532
class BitcoinApplication: public QApplication
5633
{
@@ -113,7 +90,7 @@ public Q_SLOTS:
11390
bool event(QEvent* e) override;
11491

11592
private:
116-
QThread *coreThread;
93+
std::optional<InitExecutor> m_executor;
11794
OptionsModel *optionsModel;
11895
ClientModel *clientModel;
11996
BitcoinGUI *window;

src/qt/initexecutor.cpp

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright (c) 2014-2021 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <qt/initexecutor.h>
6+
7+
#include <interfaces/node.h>
8+
#include <util/system.h>
9+
#include <util/threadnames.h>
10+
11+
#include <exception>
12+
13+
#include <QApplication>
14+
#include <QDebug>
15+
#include <QObject>
16+
#include <QProcess>
17+
#include <QString>
18+
#include <QThread>
19+
20+
InitExecutor::InitExecutor(interfaces::Node& node)
21+
: QObject(), m_node(node)
22+
{
23+
this->moveToThread(&m_thread);
24+
m_thread.start();
25+
}
26+
27+
InitExecutor::~InitExecutor()
28+
{
29+
qDebug() << __func__ << ": Stopping thread";
30+
m_thread.quit();
31+
m_thread.wait();
32+
qDebug() << __func__ << ": Stopped thread";
33+
}
34+
35+
void InitExecutor::handleRunawayException(const std::exception_ptr e)
36+
{
37+
PrintExceptionContinue(e, "Runaway exception");
38+
Q_EMIT runawayException(QString::fromStdString(m_node.getWarnings().translated));
39+
}
40+
41+
void InitExecutor::initialize()
42+
{
43+
try {
44+
util::ThreadRename("qt-init");
45+
qDebug() << __func__ << ": Running initialization in thread";
46+
interfaces::BlockAndHeaderTipInfo tip_info;
47+
bool rv = m_node.appInitMain(&tip_info);
48+
Q_EMIT initializeResult(rv, tip_info);
49+
} catch (...) {
50+
handleRunawayException(std::current_exception());
51+
}
52+
}
53+
54+
void InitExecutor::restart(QStringList args)
55+
{
56+
static bool executing_restart{false};
57+
58+
if(!executing_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
59+
executing_restart = true;
60+
try {
61+
qDebug() << __func__ << ": Running Restart in thread";
62+
m_node.appPrepareShutdown();
63+
qDebug() << __func__ << ": Shutdown finished";
64+
Q_EMIT shutdownResult();
65+
CExplicitNetCleanup::callCleanup();
66+
QProcess::startDetached(QApplication::applicationFilePath(), args);
67+
qDebug() << __func__ << ": Restart initiated...";
68+
QApplication::quit();
69+
} catch (...) {
70+
handleRunawayException(std::current_exception());
71+
}
72+
}
73+
}
74+
75+
void InitExecutor::shutdown()
76+
{
77+
try {
78+
qDebug() << __func__ << ": Running Shutdown in thread";
79+
m_node.appShutdown();
80+
qDebug() << __func__ << ": Shutdown finished";
81+
Q_EMIT shutdownResult();
82+
} catch (...) {
83+
handleRunawayException(std::current_exception());
84+
}
85+
}

0 commit comments

Comments
 (0)