mirror of
https://github.com/mollyim/monero-wallet-sdk.git
synced 2025-02-04 08:55:39 -05:00
lib: use a mutex for the refresh outer loop
This commit is contained in:
parent
a34ace5fc8
commit
a7b4c0caa9
@ -35,7 +35,8 @@ Wallet::Wallet(
|
||||
m_account_ready(false),
|
||||
m_blockchain_height(1),
|
||||
m_restore_height(0),
|
||||
m_refresh_continue(false) {
|
||||
m_refresh_running(false),
|
||||
m_refresh_stopped(false) {
|
||||
// Use a bogus ipv6 address as a placeholder for the daemon address.
|
||||
LOG_FATAL_IF(!m_wallet.init("[100::/64]", {}, {}, 0, false),
|
||||
"Init failed");
|
||||
@ -146,30 +147,39 @@ void Wallet::handleNewBlock(uint64_t height) {
|
||||
}
|
||||
|
||||
Wallet::Status Wallet::refreshLoopUntilSynced(bool skip_coinbase) {
|
||||
std::unique_lock<std::mutex> lock(m_wallet_mutex);
|
||||
m_refresh_continue = true;
|
||||
Status ret = Status::INTERRUPTED;
|
||||
while (m_refresh_continue) {
|
||||
Status ret;
|
||||
std::unique_lock<std::mutex> refresh_lock(m_refresh_mutex);
|
||||
m_refresh_stopped = false;
|
||||
for (;;) {
|
||||
std::lock_guard<std::mutex> wallet_lock(m_wallet_mutex);
|
||||
if (m_refresh_stopped) {
|
||||
ret = Status::INTERRUPTED;
|
||||
break;
|
||||
}
|
||||
m_refresh_running = true;
|
||||
m_wallet.set_refresh_type(skip_coinbase ? tools::wallet2::RefreshType::RefreshNoCoinbase
|
||||
: tools::wallet2::RefreshType::RefreshDefault);
|
||||
m_wallet.set_refresh_from_block_height(m_restore_height);
|
||||
try {
|
||||
m_wallet.set_refresh_type(skip_coinbase ? tools::wallet2::RefreshType::RefreshNoCoinbase
|
||||
: tools::wallet2::RefreshType::RefreshDefault);
|
||||
m_wallet.set_refresh_from_block_height(m_restore_height);
|
||||
// It will block until we call stop() or it sync successfully.
|
||||
// Calling refresh() will block until stop() is called or it sync successfully.
|
||||
m_wallet.refresh(false);
|
||||
if (!m_wallet.stopped()) {
|
||||
ret = Status::OK;
|
||||
break;
|
||||
}
|
||||
} catch (const tools::error::no_connection_to_daemon&) {
|
||||
m_refresh_running = false;
|
||||
ret = Status::NO_NETWORK_CONNECTIVITY;
|
||||
break;
|
||||
} catch (const tools::error::refresh_error) {
|
||||
m_refresh_running = false;
|
||||
ret = Status::REFRESH_ERROR;
|
||||
break;
|
||||
}
|
||||
m_refresh_cond.wait(lock);
|
||||
m_refresh_running = false;
|
||||
if (!m_wallet.stopped()) {
|
||||
ret = Status::OK;
|
||||
break;
|
||||
}
|
||||
m_refresh_cond.wait(refresh_lock);
|
||||
}
|
||||
lock.unlock();
|
||||
refresh_lock.unlock();
|
||||
// Always notify the last block height.
|
||||
m_callback.callVoidMethod(getJniEnv(), Wallet_onRefresh, m_blockchain_height, false);
|
||||
return ret;
|
||||
@ -177,31 +187,37 @@ Wallet::Status Wallet::refreshLoopUntilSynced(bool skip_coinbase) {
|
||||
|
||||
template<typename T>
|
||||
auto Wallet::pauseRefreshAndRunLocked(T block) -> decltype(block()) {
|
||||
std::unique_lock<std::mutex> lock(m_wallet_mutex, std::defer_lock);
|
||||
while (!lock.try_lock()) {
|
||||
m_wallet.stop();
|
||||
std::this_thread::yield();
|
||||
std::unique_lock<std::mutex> refresh_lock(m_refresh_mutex, std::try_to_lock);
|
||||
if (!refresh_lock.owns_lock()) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
do {
|
||||
if (refresh_is_running()) {
|
||||
m_wallet.stop();
|
||||
m_remote_node_client.callVoidMethod(env, IRemoteNodeClient_cancelAll);
|
||||
}
|
||||
std::this_thread::yield();
|
||||
} while (!refresh_lock.try_lock());
|
||||
}
|
||||
auto res = block();
|
||||
LOG_FATAL_IF(refresh_is_running());
|
||||
std::lock_guard<std::mutex> wallet_lock(m_wallet_mutex);
|
||||
m_refresh_mutex.unlock();
|
||||
m_refresh_cond.notify_one();
|
||||
return res;
|
||||
return block();
|
||||
}
|
||||
|
||||
void Wallet::stopRefresh() {
|
||||
pauseRefreshAndRunLocked([&]() -> int {
|
||||
m_refresh_continue = false;
|
||||
return 0;
|
||||
pauseRefreshAndRunLocked([&]() {
|
||||
m_refresh_stopped = true;
|
||||
});
|
||||
}
|
||||
|
||||
void Wallet::setRefreshSince(long height_or_timestamp) {
|
||||
pauseRefreshAndRunLocked([&]() -> int {
|
||||
pauseRefreshAndRunLocked([&]() {
|
||||
if (height_or_timestamp < CRYPTONOTE_MAX_BLOCK_NUMBER) {
|
||||
m_restore_height = height_or_timestamp;
|
||||
} else {
|
||||
LOG_FATAL("TODO");
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ class Wallet : tools::i_wallet2_callback {
|
||||
|
||||
uint64_t current_blockchain_height() const { return m_blockchain_height; }
|
||||
|
||||
bool refresh_is_running() const { return m_refresh_continue; }
|
||||
bool refresh_is_running() const { return m_refresh_running; }
|
||||
|
||||
// Extra object's state that need to be persistent.
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
@ -65,13 +65,15 @@ class Wallet : tools::i_wallet2_callback {
|
||||
// Protects access to m_wallet instance and state fields.
|
||||
std::mutex m_wallet_mutex;
|
||||
std::mutex m_tx_outs_mutex;
|
||||
std::mutex m_refresh_mutex;
|
||||
|
||||
// Reference to the Wallet kotlin instance.
|
||||
// Reference to Kotlin instances.
|
||||
const ScopedJvmGlobalRef<jobject> m_remote_node_client;
|
||||
const ScopedJvmGlobalRef<jobject> m_callback;
|
||||
|
||||
std::condition_variable m_refresh_cond;
|
||||
bool m_refresh_started;
|
||||
bool m_refresh_continue;
|
||||
bool m_refresh_running;
|
||||
bool m_refresh_stopped;
|
||||
|
||||
template<typename T>
|
||||
auto pauseRefreshAndRunLocked(T block) -> decltype(block());
|
||||
|
Loading…
x
Reference in New Issue
Block a user