From 28a642b5bcdd9531139047508ff5ba000f5fad3f Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 10 Aug 2019 11:40:45 -0400 Subject: [PATCH] compiling with vector m_listeners --- src/wallet/monero_wallet.cpp | 77 +++++++++++++++++++----------------- src/wallet/monero_wallet.h | 26 ++++++++---- test/sample_code.cpp | 2 +- 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 63aad05..665528b 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -652,7 +652,7 @@ namespace monero { // ----------------------------- WALLET LISTENER ---------------------------- /** - * Listens to wallet2 notifications in order to facilitate external wallet notifications. + * Listens to wallet2 notifications in order to notify external wallet listeners. */ struct wallet2_listener : public tools::i_wallet2_callback { @@ -661,58 +661,53 @@ namespace monero { /** * Constructs the listener. * - * @param wallet provides context to inform external notifications + * @param wallet provides context to notify external listeners * @param wallet2 provides source notifications which this listener propagates to external listeners */ wallet2_listener(monero_wallet& wallet, tools::wallet2& m_w2) : m_wallet(wallet), m_w2(m_w2) { - this->m_listener = boost::none; this->m_sync_start_height = boost::none; this->m_sync_end_height = boost::none; - this->m_sync_listener = boost::none; } ~wallet2_listener() { MTRACE("~wallet2_listener()"); } - void set_wallet_listener(boost::optional listener) { - this->m_listener = listener; - update_listening(); + void update_listening() { + //m_w2.callback(m_wallet.get_listeners().empty() ? nullptr : this); } - void on_sync_start(uint64_t start_height, boost::optional sync_listener) { + void on_sync_start(uint64_t start_height) { if (m_sync_start_height != boost::none || m_sync_end_height != boost::none) throw runtime_error("Sync start or end height should not already be allocated, is previous sync in progress?"); m_sync_start_height = start_height; m_sync_end_height = m_wallet.get_daemon_height(); - this->m_sync_listener = sync_listener; - update_listening(); } void on_sync_end() { m_sync_start_height = boost::none; m_sync_end_height = boost::none; - m_sync_listener = boost::none; - update_listening(); } virtual void on_new_block(uint64_t height, const cryptonote::block& cn_block) { - // notify listener of block - if (m_listener != boost::none) m_listener->on_new_block(height); + // notify listeners of block + for (monero_wallet_listener* listener : m_wallet.get_listeners()) { + listener->on_new_block(height); + } // notify listeners of sync progress if (m_sync_start_height != boost::none && height >= *m_sync_start_height) { if (height >= *m_sync_end_height) m_sync_end_height = height + 1; // increase end height if necessary double percent_done = (double) (height - *m_sync_start_height + 1) / (double) (*m_sync_end_height - *m_sync_start_height); string message = string("Synchronizing"); - if (m_listener != boost::none) m_listener.get().on_sync_progress(height, *m_sync_start_height, *m_sync_end_height, percent_done, message); - if (m_sync_listener != boost::none) m_sync_listener.get().on_sync_progress(height, *m_sync_start_height, *m_sync_end_height, percent_done, message); + for (monero_wallet_listener* listener : m_wallet.get_listeners()) { + listener->on_sync_progress(height, *m_sync_start_height, *m_sync_end_height, percent_done, message); + } } } virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& cn_tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, uint64_t unlock_time) { MTRACE("wallet2_listener::on_money_received()"); - if (m_listener == boost::none) return; // create native library tx shared_ptr block = make_shared(); @@ -729,8 +724,10 @@ namespace monero { output->m_account_index = subaddr_index.major; output->m_subaddress_index = subaddr_index.minor; - // notify listener of output - m_listener->on_output_received(*output); + // notify listeners of output + for (monero_wallet_listener* listener : m_wallet.get_listeners()) { + listener->on_output_received(*output); + } } virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& cn_tx_in, uint64_t amount, const cryptonote::transaction& cn_tx_out, const cryptonote::subaddress_index& subaddr_index) { @@ -751,8 +748,10 @@ namespace monero { output->m_account_index = subaddr_index.major; output->m_subaddress_index = subaddr_index.minor; - // notify listener of output - m_listener->on_output_spent(*output); + // notify listeners of output + for (monero_wallet_listener* listener : m_wallet.get_listeners()) { + listener->on_output_spent(*output); + } // TODO **: to notify or not to notify? // std::string tx_hash = epee::string_tools::pod_to_hex(txid); @@ -770,14 +769,8 @@ namespace monero { private: monero_wallet& m_wallet; // wallet to provide context for notifications tools::wallet2& m_w2; // internal wallet implementation to listen to - boost::optional m_listener; // target listener to invoke with notifications - boost::optional m_sync_listener; boost::optional m_sync_start_height; boost::optional m_sync_end_height; - - void update_listening() { - m_w2.callback(m_listener == boost::none && m_sync_listener == boost::none ? nullptr : this); - } }; // ---------------------------- WALLET MANAGEMENT --------------------------- @@ -1121,9 +1114,21 @@ namespace monero { return get_address(0, 0); } - void monero_wallet::set_listener(const boost::optional listener) { - MTRACE("set_listener()"); - m_w2_listener->set_wallet_listener(listener); + void monero_wallet::add_listener(monero_wallet_listener& listener) { + MTRACE("add_listener()"); + m_listeners.push_back(&listener); + m_w2_listener->update_listening(); + } + + void monero_wallet::remove_listener(monero_wallet_listener& listener) { + MTRACE("remove_listener()"); + m_listeners.erase(remove(m_listeners.begin(), m_listeners.end(), &listener), m_listeners.end()); + m_w2_listener->update_listening(); + } + + vector monero_wallet::get_listeners() { + MTRACE("get_listeners()"); + return m_listeners; } monero_sync_result monero_wallet::sync() { @@ -1135,7 +1140,7 @@ namespace monero { monero_sync_result monero_wallet::sync(monero_sync_listener& listener) { MTRACE("sync(listener)"); if (!m_is_connected) throw runtime_error("Wallet is not connected to daemon"); - return lock_and_sync(boost::none, listener); + return lock_and_sync(boost::none); } monero_sync_result monero_wallet::sync(uint64_t start_height) { @@ -1147,7 +1152,7 @@ namespace monero { monero_sync_result monero_wallet::sync(uint64_t start_height, monero_sync_listener& listener) { MTRACE("sync(" << start_height << ", listener)"); if (!m_is_connected) throw runtime_error("Wallet is not connected to daemon"); - return lock_and_sync(start_height, listener); + return lock_and_sync(start_height); } /** @@ -2498,7 +2503,7 @@ namespace monero { } } - monero_sync_result monero_wallet::lock_and_sync(boost::optional start_height, boost::optional listener) { + monero_sync_result monero_wallet::lock_and_sync(boost::optional start_height) { bool rescan = m_rescan_on_sync.exchange(false); boost::lock_guard guarg(m_sync_mutex); // synchronize sync() and syncAsync() monero_sync_result result; @@ -2512,7 +2517,7 @@ namespace monero { if (rescan) m_w2->rescan_blockchain(false); // sync wallet - result = sync_aux(start_height, listener); + result = sync_aux(start_height); // find and save rings m_w2->find_and_save_rings(false); @@ -2521,7 +2526,7 @@ namespace monero { return result; } - monero_sync_result monero_wallet::sync_aux(boost::optional start_height, boost::optional listener) { + monero_sync_result monero_wallet::sync_aux(boost::optional start_height) { MTRACE("sync_aux()"); // determine sync start height @@ -2529,7 +2534,7 @@ namespace monero { if (sync_start_height < get_restore_height()) set_restore_height(sync_start_height); // TODO monero core: start height processed > requested start height unless restore height manually set // sync wallet and return result - m_w2_listener->on_sync_start(sync_start_height, listener); + m_w2_listener->on_sync_start(sync_start_height); monero_sync_result result; m_w2->refresh(m_w2->is_trusted_daemon(), sync_start_height, result.m_num_blocks_fetched, result.m_received_money, true); if (!m_is_synced) m_is_synced = true; diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 28ae564..5d4f673 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -386,11 +386,23 @@ namespace monero { monero_integrated_address decode_integrated_address(const string& integrated_address) const; /** - * Set the wallet's listener to receive wallet notifications. + * Register a listener receive wallet notifications. * * @param listener is the listener to receive wallet notifications */ - void set_listener(boost::optional listener); + void add_listener(monero_wallet_listener& listener); + + /** + * Unregister a listener to receive wallet notifications. + * + * @param listener is the listener to unregister + */ + void remove_listener(monero_wallet_listener& listener); + + /** + * Get the listeners registered with the wallet. + */ + vector get_listeners(); /** * Synchronize the wallet with the daemon as a one-time synchronous process. @@ -1286,9 +1298,9 @@ namespace monero { private: friend struct wallet2_listener; - unique_ptr m_w2; // internal wallet implementation - unique_ptr m_w2_listener; // listener for internal wallet implementation - boost::optional m_listener = boost::none; // wallet's external listener + unique_ptr m_w2; // internal wallet implementation + unique_ptr m_w2_listener; // internal wallet implementation listener + vector m_listeners; // external wallet listeners void init_common(); vector get_subaddresses_aux(uint32_t account_idx, const vector& subaddress_indices, const vector& transfers) const; @@ -1305,7 +1317,7 @@ namespace monero { boost::mutex m_syncing_mutex; // synchronize auto sync loop std::atomic m_syncing_thread_done; // whether or not the syncing thread is shut down void sync_thread_func(); // function to run thread with syncing loop - monero_sync_result lock_and_sync(boost::optional start_height = boost::none, boost::optional listener = boost::none); // internal function to synchronize request to sync and rescan - monero_sync_result sync_aux(boost::optional start_height = boost::none, boost::optional listener = boost::none); // internal function to immediately block, sync, and report progress + monero_sync_result lock_and_sync(boost::optional start_height = boost::none); // internal function to synchronize request to sync and rescan + monero_sync_result sync_aux(boost::optional start_height = boost::none); // internal function to immediately block, sync, and report progress }; } diff --git a/test/sample_code.cpp b/test/sample_code.cpp index 5068c38..7eb5cb6 100644 --- a/test/sample_code.cpp +++ b/test/sample_code.cpp @@ -88,7 +88,7 @@ int main(int argc, const char* argv[]) { shared_ptr key_image = output.m_key_image.get(); } } my_listener; - wallet_random->set_listener(my_listener); + wallet_random->add_listener(my_listener); // send funds from the restored wallet to the random wallet shared_ptr sent_tx = wallet_restored->send(0, wallet_random->get_address(1, 0), 50000);