qt: get required locks upfront in polling functions
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.
This commit is contained in:
parent
ed67100565
commit
41106a50d2
3 changed files with 34 additions and 18 deletions
|
@ -92,6 +92,12 @@ 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();
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <QDebug>
|
||||
#include <QIcon>
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
|
||||
// Amount column is right-aligned it contains numbers
|
||||
static int column_alignments[] = {
|
||||
|
@ -187,17 +186,25 @@ public:
|
|||
{
|
||||
TransactionRecord *rec = &cachedWallet[idx];
|
||||
|
||||
// Get required locks upfront. This avoids the GUI from getting
|
||||
// stuck if the core is holding the locks for a longer time - for
|
||||
// example, during a wallet rescan.
|
||||
//
|
||||
// If a status update is needed (blocks came in since last check),
|
||||
// update the status of this transaction from the wallet. Otherwise,
|
||||
// simply re-use the cached status.
|
||||
LOCK2(cs_main, wallet->cs_wallet);
|
||||
if(rec->statusUpdateNeeded())
|
||||
TRY_LOCK(cs_main, lockMain);
|
||||
if(lockMain)
|
||||
{
|
||||
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
|
||||
|
||||
if(mi != wallet->mapWallet.end())
|
||||
TRY_LOCK(wallet->cs_wallet, lockWallet);
|
||||
if(lockWallet && rec->statusUpdateNeeded())
|
||||
{
|
||||
rec->updateStatus(mi->second);
|
||||
std::map<uint256, CWalletTx>::iterator mi = wallet->mapWallet.find(rec->hash);
|
||||
|
||||
if(mi != wallet->mapWallet.end())
|
||||
{
|
||||
rec->updateStatus(mi->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rec;
|
||||
|
|
|
@ -98,18 +98,21 @@ void WalletModel::updateStatus()
|
|||
|
||||
void WalletModel::pollBalanceChanged()
|
||||
{
|
||||
bool heightChanged = false;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if(chainActive.Height() != cachedNumBlocks)
|
||||
{
|
||||
// Balance and number of transactions might have changed
|
||||
cachedNumBlocks = chainActive.Height();
|
||||
heightChanged = true;
|
||||
}
|
||||
}
|
||||
if(heightChanged)
|
||||
// Get required locks 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;
|
||||
TRY_LOCK(wallet->cs_wallet, lockWallet);
|
||||
if(!lockWallet)
|
||||
return;
|
||||
|
||||
if(chainActive.Height() != cachedNumBlocks)
|
||||
{
|
||||
// Balance and number of transactions might have changed
|
||||
cachedNumBlocks = chainActive.Height();
|
||||
|
||||
checkBalanceChanged();
|
||||
if(transactionTableModel)
|
||||
transactionTableModel->updateConfirmations();
|
||||
|
|
Loading…
Reference in a new issue