aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorluigi1111 <luigi1111w@gmail.com>2020-10-13 12:38:40 -0500
committerluigi1111 <luigi1111w@gmail.com>2020-10-13 12:38:40 -0500
commit381442a1386c1319034c1335f01040da2306dd31 (patch)
treef507d6fc8a3de36ee12c4439ad2d68d8eb62e5ba /src
parent7cb24f50b8676748212e57017b043ba1e7b08033 (diff)
parent39d9d7d071dd9ed7a942578a7db520ac0ec08f5e (diff)
downloadmonzero-gui-381442a1386c1319034c1335f01040da2306dd31.tar.gz
monzero-gui-381442a1386c1319034c1335f01040da2306dd31.tar.xz
monzero-gui-381442a1386c1319034c1335f01040da2306dd31.zip
Merge pull request #3145
39d9d7d Wallet: rework wallet refreshing (xiphon)
Diffstat (limited to 'src')
-rw-r--r--src/libwalletqt/Wallet.cpp107
-rw-r--r--src/libwalletqt/Wallet.h24
-rw-r--r--src/qt/FutureScheduler.cpp5
-rw-r--r--src/qt/FutureScheduler.h3
4 files changed, 97 insertions, 42 deletions
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index 508f105e..454dca29 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -27,6 +27,11 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Wallet.h"
+
+#include <chrono>
+#include <stdexcept>
+#include <thread>
+
#include "PendingTransaction.h"
#include "UnsignedTransaction.h"
#include "TransactionHistory.h"
@@ -50,6 +55,8 @@
#include <QVector>
#include <QMutexLocker>
+#include "qt/ScopeGuard.h"
+
namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@@ -124,6 +131,19 @@ bool Wallet::disconnected() const
return m_disconnected;
}
+bool Wallet::refreshing() const
+{
+ return m_refreshing;
+}
+
+void Wallet::refreshingSet(bool value)
+{
+ if (m_refreshing.exchange(value) != value)
+ {
+ emit refreshingChanged();
+ }
+}
+
void Wallet::setConnectionStatus(ConnectionStatus value)
{
if (m_connectionStatus == value)
@@ -196,7 +216,7 @@ void Wallet::storeAsync(const QJSValue &callback, const QString &path /* = "" */
{
const auto future = m_scheduler.run(
[this, path] {
- QMutexLocker locker(&m_storeMutex);
+ QMutexLocker locker(&m_asyncMutex);
return QJSValueList({m_walletImpl->store(path.toStdString())});
},
@@ -263,7 +283,7 @@ void Wallet::initAsync(
emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh";
connected(true);
- m_walletImpl->startRefresh();
+ startRefresh();
}
});
if (future.first)
@@ -466,41 +486,37 @@ bool Wallet::importKeyImages(const QString& path)
return m_walletImpl->importKeyImages(path.toStdString());
}
-bool Wallet::refresh()
-{
- bool result = m_walletImpl->refresh();
- m_history->refresh(currentSubaddressAccount());
- m_subaddress->refresh(currentSubaddressAccount());
- m_subaddressAccount->getAll();
- if (result)
- emit updated();
- return result;
-}
-
-void Wallet::refreshAsync()
+bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
{
- qDebug() << "refresh async";
- m_walletImpl->refreshAsync();
-}
+ refreshingSet(true);
+ const auto cleanup = sg::make_scope_guard([this]() noexcept {
+ refreshingSet(false);
+ });
-void Wallet::setAutoRefreshInterval(int seconds)
-{
- m_walletImpl->setAutoRefreshInterval(seconds);
-}
+ {
+ QMutexLocker locker(&m_asyncMutex);
-int Wallet::autoRefreshInterval() const
-{
- return m_walletImpl->autoRefreshInterval();
+ bool result = m_walletImpl->refresh();
+ if (historyAndSubaddresses)
+ {
+ m_history->refresh(currentSubaddressAccount());
+ m_subaddress->refresh(currentSubaddressAccount());
+ m_subaddressAccount->getAll();
+ }
+ if (result)
+ emit updated();
+ return result;
+ }
}
-void Wallet::startRefresh() const
+void Wallet::startRefresh()
{
- m_walletImpl->startRefresh();
+ m_refreshEnabled = true;
}
-void Wallet::pauseRefresh() const
+void Wallet::pauseRefresh()
{
- m_walletImpl->pauseRefresh();
+ m_refreshEnabled = false;
}
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -874,6 +890,8 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
bool Wallet::rescanSpent()
{
+ QMutexLocker locker(&m_asyncMutex);
+
return m_walletImpl->rescanSpent();
}
@@ -1041,6 +1059,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr)
+ , m_refreshEnabled(false)
+ , m_refreshing(false)
, m_scheduler(this)
{
m_history = new TransactionHistory(m_walletImpl->history(), this);
@@ -1058,6 +1078,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false;
m_daemonUsername = "";
m_daemonPassword = "";
+
+ startRefreshThread();
}
Wallet::~Wallet()
@@ -1090,3 +1112,32 @@ Wallet::~Wallet()
m_walletListener = NULL;
qDebug("m_walletImpl deleted");
}
+
+void Wallet::startRefreshThread()
+{
+ const auto future = m_scheduler.run([this] {
+ static constexpr const size_t refreshIntervalSec = 10;
+ static constexpr const size_t intervalResolutionMs = 100;
+
+ auto last = std::chrono::steady_clock::now();
+ while (!m_scheduler.stopping())
+ {
+ if (m_refreshEnabled)
+ {
+ const auto now = std::chrono::steady_clock::now();
+ const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - last).count();
+ if (elapsed >= refreshIntervalSec)
+ {
+ refresh(false);
+ last = std::chrono::steady_clock::now();
+ }
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(intervalResolutionMs));
+ }
+ });
+ if (!future.first)
+ {
+ throw std::runtime_error("failed to start auto refresh thread");
+ }
+}
diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h
index b099a011..42e30336 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -63,6 +63,7 @@ class Wallet : public QObject, public PassprasePrompter
{
Q_OBJECT
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
+ Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
Q_PROPERTY(QString seed READ getSeed)
Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status)
@@ -207,20 +208,11 @@ public:
Q_INVOKABLE bool importKeyImages(const QString& path);
//! refreshes the wallet
- Q_INVOKABLE bool refresh();
-
- //! refreshes the wallet asynchronously
- Q_INVOKABLE void refreshAsync();
-
- //! setup auto-refresh interval in seconds
- Q_INVOKABLE void setAutoRefreshInterval(int seconds);
-
- //! return auto-refresh interval in seconds
- Q_INVOKABLE int autoRefreshInterval() const;
+ Q_INVOKABLE bool refresh(bool historyAndSubaddresses = true);
// pause/resume refresh
- Q_INVOKABLE void startRefresh() const;
- Q_INVOKABLE void pauseRefresh() const;
+ Q_INVOKABLE void startRefresh();
+ Q_INVOKABLE void pauseRefresh();
//! creates transaction
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -394,6 +386,7 @@ signals:
void currentSubaddressAccountChanged() const;
void disconnectedChanged() const;
void proxyAddressChanged() const;
+ void refreshingChanged() const;
private:
Wallet(QObject * parent = nullptr);
@@ -421,9 +414,12 @@ private:
const QString& proxyAddress);
bool disconnected() const;
+ bool refreshing() const;
+ void refreshingSet(bool value);
void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const;
void setProxyAddress(QString address);
+ void startRefreshThread();
private:
friend class WalletManager;
@@ -454,15 +450,17 @@ private:
mutable SubaddressModel * m_subaddressModel;
SubaddressAccount * m_subaddressAccount;
mutable SubaddressAccountModel * m_subaddressAccountModel;
+ QMutex m_asyncMutex;
QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning;
QString m_daemonUsername;
QString m_daemonPassword;
QString m_proxyAddress;
mutable QMutex m_proxyMutex;
+ std::atomic<bool> m_refreshEnabled;
+ std::atomic<bool> m_refreshing;
WalletListenerImpl *m_walletListener;
FutureScheduler m_scheduler;
- QMutex m_storeMutex;
};
diff --git a/src/qt/FutureScheduler.cpp b/src/qt/FutureScheduler.cpp
index b15101e4..f83b5e7f 100644
--- a/src/qt/FutureScheduler.cpp
+++ b/src/qt/FutureScheduler.cpp
@@ -65,6 +65,11 @@ QPair<bool, QFuture<QJSValueList>> FutureScheduler::run(std::function<QJSValueLi
});
}
+bool FutureScheduler::stopping() const noexcept
+{
+ return Stopping;
+}
+
bool FutureScheduler::add() noexcept
{
QMutexLocker locker(&Mutex);
diff --git a/src/qt/FutureScheduler.h b/src/qt/FutureScheduler.h
index ab9f323d..b5905956 100644
--- a/src/qt/FutureScheduler.h
+++ b/src/qt/FutureScheduler.h
@@ -23,6 +23,7 @@ public:
QPair<bool, QFuture<void>> run(std::function<void()> function) noexcept;
QPair<bool, QFuture<QJSValueList>> run(std::function<QJSValueList()> function, const QJSValue &callback);
+ bool stopping() const noexcept;
private:
bool add() noexcept;
@@ -59,7 +60,7 @@ private:
size_t Alive;
QWaitCondition Condition;
QMutex Mutex;
- bool Stopping;
+ std::atomic<bool> Stopping;
};
#endif // FUTURE_SCHEDULER_H