From e6d50fcdecfdd7281b7aa5e9b573ef1b4e82873f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 26 Nov 2015 16:39:40 +0100 Subject: [Qt] update block tip (height and date) without locking cs_main, update always (each block) --- src/qt/clientmodel.cpp | 53 ++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) (limited to 'src/qt/clientmodel.cpp') diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 566e8fa62..92df336c9 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -23,16 +23,13 @@ #include static const int64_t nClientStartupTime = GetTime(); +static int64_t nLastBlockTipUpdateNotification = 0; ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : QObject(parent), optionsModel(optionsModel), peerTableModel(0), banTableModel(0), - cachedNumBlocks(0), - cachedBlockDate(QDateTime()), - cachedReindexing(0), - cachedImporting(0), pollTimer(0) { peerTableModel = new PeerTableModel(this); @@ -107,32 +104,8 @@ double ClientModel::getVerificationProgress() const void ClientModel::updateTimer() { - // Get required lock upfront. This avoids the GUI from getting stuck on - // periodical polls if the core is holding the locks for a longer time - - // for example, during a wallet rescan. - TRY_LOCK(cs_main, lockMain); - if (!lockMain) - return; - - // Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change. - // Periodically check and update with a timer. - int newNumBlocks = getNumBlocks(); - QDateTime newBlockDate = getLastBlockDate(); - - // check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state - if (cachedNumBlocks != newNumBlocks || - cachedBlockDate != newBlockDate || - cachedReindexing != fReindex || - cachedImporting != fImporting) - { - cachedNumBlocks = newNumBlocks; - cachedBlockDate = newBlockDate; - cachedReindexing = fReindex; - cachedImporting = fImporting; - - Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate); - } - + // no locking required at this point + // the following calls will aquire the required lock Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage()); Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); } @@ -261,6 +234,24 @@ static void BannedListChanged(ClientModel *clientmodel) QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection); } +static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex) +{ + // lock free async UI updates in case we have a new block tip + // during initial sync, only update the UI if the last update + // was > 250ms (MODEL_UPDATE_DELAY) ago + int64_t now = 0; + if (initialSync) + now = GetTimeMillis(); + + // if we are in-sync, update the UI regardless of last update time + if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) { + //pass a async signal to the UI thread + Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime())); + nLastBlockTipUpdateNotification = now; + } + +} + void ClientModel::subscribeToCoreSignals() { // Connect signals to client @@ -268,6 +259,7 @@ void ClientModel::subscribeToCoreSignals() uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); + uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2)); } void ClientModel::unsubscribeFromCoreSignals() @@ -277,4 +269,5 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); + uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2)); } -- cgit v1.2.3 From 947d20b84ab271bec5ff08312921961627d1ad80 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 27 Nov 2015 13:20:46 +0100 Subject: [Qt] reduce cs_main in getVerificationProgress() --- src/qt/clientmodel.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/qt/clientmodel.cpp') diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 92df336c9..f7d8b7174 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -22,6 +22,8 @@ #include #include +class CBlockIndex; + static const int64_t nClientStartupTime = GetTime(); static int64_t nLastBlockTipUpdateNotification = 0; @@ -96,10 +98,9 @@ size_t ClientModel::getMempoolDynamicUsage() const return mempool.DynamicMemoryUsage(); } -double ClientModel::getVerificationProgress() const +double ClientModel::getVerificationProgress(const CBlockIndex *tip) const { - LOCK(cs_main); - return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()); + return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), (CBlockIndex *)tip); } void ClientModel::updateTimer() @@ -246,7 +247,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB // if we are in-sync, update the UI regardless of last update time if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread - Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime())); + Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime()), pIndex); nLastBlockTipUpdateNotification = now; } -- cgit v1.2.3 From 4082e4660305f7696949c3a13e2e9611210894e8 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 27 Nov 2015 18:22:18 +0100 Subject: [Qt] call GuessVerificationProgress synchronous during core signal, pass double over UI signal --- src/qt/clientmodel.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/qt/clientmodel.cpp') diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index f7d8b7174..d36d129c1 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -98,9 +98,15 @@ size_t ClientModel::getMempoolDynamicUsage() const return mempool.DynamicMemoryUsage(); } -double ClientModel::getVerificationProgress(const CBlockIndex *tip) const +double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const { - return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), (CBlockIndex *)tip); + CBlockIndex *tip = const_cast(tipIn); + if (!tip) + { + LOCK(cs_main); + tip = chainActive.Tip(); + } + return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), tip); } void ClientModel::updateTimer() @@ -247,10 +253,9 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB // if we are in-sync, update the UI regardless of last update time if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) { //pass a async signal to the UI thread - Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime()), pIndex); + Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime()), clientmodel->getVerificationProgress(pIndex)); nLastBlockTipUpdateNotification = now; } - } void ClientModel::subscribeToCoreSignals() -- cgit v1.2.3