Skip to content

Commit

Permalink
Merge commit '2771a18' into LokiMergeUpstream20180821
Browse files Browse the repository at this point in the history
  • Loading branch information
Doy-lee committed Sep 14, 2018
2 parents c19976a + 2771a18 commit f8d1247
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 53 deletions.
37 changes: 26 additions & 11 deletions src/common/threadpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "common/util.h"

static __thread int depth = 0;
static __thread bool is_leaf = false;

namespace tools
{
Expand Down Expand Up @@ -66,26 +67,31 @@ void threadpool::start(unsigned int max_threads) {
boost::thread::attributes attrs;
attrs.set_stack_size(THREAD_STACK_SIZE);
max = max_threads ? max_threads : tools::get_max_concurrency();
unsigned int i = max;
size_t i = max ? max - 1 : 0;
while(i--) {
threads.push_back(boost::thread(attrs, boost::bind(&threadpool::run, this)));
threads.push_back(boost::thread(attrs, boost::bind(&threadpool::run, this, false)));
}
}

void threadpool::submit(waiter *obj, std::function<void()> f) {
entry e = {obj, f};
void threadpool::submit(waiter *obj, std::function<void()> f, bool leaf) {
CHECK_AND_ASSERT_THROW_MES(!is_leaf, "A leaf routine is using a thread pool");
boost::unique_lock<boost::mutex> lock(mutex);
if ((active == max && !queue.empty()) || depth > 0) {
if (!leaf && ((active == max && !queue.empty()) || depth > 0)) {
// if all available threads are already running
// and there's work waiting, just run in current thread
lock.unlock();
++depth;
is_leaf = leaf;
f();
--depth;
is_leaf = false;
} else {
if (obj)
obj->inc();
queue.push_back(e);
if (leaf)
queue.push_front({obj, f, leaf});
else
queue.push_back({obj, f, leaf});
has_work.notify_one();
}
}
Expand All @@ -103,17 +109,20 @@ threadpool::waiter::~waiter()
}
try
{
wait();
wait(NULL);
}
catch (const std::exception &e)
{
/* ignored */
}
}

void threadpool::waiter::wait() {
void threadpool::waiter::wait(threadpool *tpool) {
if (tpool)
tpool->run(true);
boost::unique_lock<boost::mutex> lock(mt);
while(num) cv.wait(lock);
while(num)
cv.wait(lock);
}

void threadpool::waiter::inc() {
Expand All @@ -125,24 +134,30 @@ void threadpool::waiter::dec() {
const boost::unique_lock<boost::mutex> lock(mt);
num--;
if (!num)
cv.notify_one();
cv.notify_all();
}

void threadpool::run() {
void threadpool::run(bool flush) {
boost::unique_lock<boost::mutex> lock(mutex);
while (running) {
entry e;
while(queue.empty() && running)
{
if (flush)
return;
has_work.wait(lock);
}
if (!running) break;

active++;
e = queue.front();
queue.pop_front();
lock.unlock();
++depth;
is_leaf = e.leaf;
e.f();
--depth;
is_leaf = false;

if (e.wo)
e.wo->dec();
Expand Down
7 changes: 4 additions & 3 deletions src/common/threadpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ class threadpool
public:
void inc();
void dec();
void wait(); //! Wait for a set of tasks to finish.
void wait(threadpool *tpool); //! Wait for a set of tasks to finish.
waiter() : num(0){}
~waiter();
};

// Submit a task to the pool. The waiter pointer may be
// NULL if the caller doesn't care to wait for the
// task to finish.
void submit(waiter *waiter, std::function<void()> f);
void submit(waiter *waiter, std::function<void()> f, bool leaf = false);

unsigned int get_max_concurrency() const;

Expand All @@ -80,6 +80,7 @@ class threadpool
typedef struct entry {
waiter *wo;
std::function<void()> f;
bool leaf;
} entry;
std::deque<entry> queue;
boost::condition_variable has_work;
Expand All @@ -88,7 +89,7 @@ class threadpool
unsigned int active;
unsigned int max;
bool running;
void run();
void run(bool flush = false);
};

}
14 changes: 7 additions & 7 deletions src/cryptonote_core/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2807,7 +2807,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,

tools::threadpool& tpool = tools::threadpool::getInstance();
tools::threadpool::waiter waiter;
const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(); });
const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(&tpool); });
int threads = tpool.get_max_concurrency();

for (const auto& txin : tx.vin)
Expand Down Expand Up @@ -2869,7 +2869,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
{
// ND: Speedup
// 1. Thread ring signature verification if possible.
tpool.submit(&waiter, boost::bind(&Blockchain::check_ring_signature, this, std::cref(tx_prefix_hash), std::cref(in_to_key.k_image), std::cref(pubkeys[sig_index]), std::cref(tx.signatures[sig_index]), std::ref(results[sig_index])));
tpool.submit(&waiter, boost::bind(&Blockchain::check_ring_signature, this, std::cref(tx_prefix_hash), std::cref(in_to_key.k_image), std::cref(pubkeys[sig_index]), std::cref(tx.signatures[sig_index]), std::ref(results[sig_index])), true);
}
else
{
Expand All @@ -2893,7 +2893,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
sig_index++;
}
if (tx.version == 1 && threads > 1)
waiter.wait();
waiter.wait(&tpool);

if (tx.version == 1)
{
Expand Down Expand Up @@ -4282,11 +4282,11 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
tools::threadpool::waiter waiter;
for (uint64_t i = 0; i < threads; i++)
{
tpool.submit(&waiter, boost::bind(&Blockchain::block_longhash_worker, this, thread_height, std::cref(blocks[i]), std::ref(maps[i])));
tpool.submit(&waiter, boost::bind(&Blockchain::block_longhash_worker, this, thread_height, std::cref(blocks[i]), std::ref(maps[i])), true);
thread_height += blocks[i].size();
}

waiter.wait();
waiter.wait(&tpool);

if (m_cancel)
return false;
Expand Down Expand Up @@ -4421,9 +4421,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
for (size_t i = 0; i < amounts.size(); i++)
{
uint64_t amount = amounts[i];
tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount]), std::ref(transactions[i])));
tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount]), std::ref(transactions[i])), true);
}
waiter.wait();
waiter.wait(&tpool);
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions src/cryptonote_core/cryptonote_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ namespace cryptonote
}
});
}
waiter.wait();
waiter.wait(&tpool);
it = tx_blobs.begin();
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
if (!results[i].res)
Expand Down Expand Up @@ -785,7 +785,7 @@ namespace cryptonote
});
}
}
waiter.wait();
waiter.wait(&tpool);

bool ok = true;
it = tx_blobs.begin();
Expand Down
12 changes: 6 additions & 6 deletions src/ringct/rctSigs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -862,9 +862,9 @@ namespace rct {
results[i] = verBulletproof(rv.p.bulletproofs[i]);
else
results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
});
}, true);
}
waiter.wait();
waiter.wait(&tpool);

for (size_t i = 0; i < rv.outPk.size(); ++i) {
if (!results[i]) {
Expand Down Expand Up @@ -970,9 +970,9 @@ namespace rct {
results[i] = verBulletproof(rv.p.bulletproofs[i]);
else
results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
});
}, true);
}
waiter.wait();
waiter.wait(&tpool);

for (size_t i = 0; i < results.size(); ++i) {
if (!results[i]) {
Expand All @@ -989,9 +989,9 @@ namespace rct {
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
tpool.submit(&waiter, [&, i] {
results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], pseudoOuts[i]);
});
}, true);
}
waiter.wait();
waiter.wait(&tpool);

for (size_t i = 0; i < results.size(); ++i) {
if (!results[i]) {
Expand Down
36 changes: 18 additions & 18 deletions src/wallet/wallet2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,9 +1267,9 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
for (size_t i = 1; i < tx.vout.size(); ++i)
{
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])));
std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])), true);
}
waiter.wait();
waiter.wait(&tpool);
// then scan all outputs from 0
hw::device &hwdev = m_account.get_device();
boost::unique_lock<hw::device> hwdev_lock (hwdev);
Expand All @@ -1289,10 +1289,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
for (size_t i = 0; i < tx.vout.size(); ++i)
{
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::cref(is_out_data_ptr), std::ref(tx_scan_info[i])));
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::cref(is_out_data_ptr), std::ref(tx_scan_info[i]), std::ref(output_found[i])), true);
}
waiter.wait();
waiter.wait(&tpool);

hw::device &hwdev = m_account.get_device();
boost::unique_lock<hw::device> hwdev_lock (hwdev);
Expand Down Expand Up @@ -1847,7 +1847,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
}
}
THROW_WALLET_EXCEPTION_IF(txidx != num_txes, error::wallet_internal_error, "txidx does not match tx_cache_data size");
waiter.wait();
waiter.wait(&tpool);

hw::device &hwdev = m_account.get_device();
hw::reset_mode rst(hwdev);
Expand All @@ -1867,11 +1867,11 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
for (auto &slot: tx_cache_data)
{
for (auto &iod: slot.primary)
tpool.submit(&waiter, [&gender, &iod]() { gender(iod); });
tpool.submit(&waiter, [&gender, &iod]() { gender(iod); }, true);
for (auto &iod: slot.additional)
tpool.submit(&waiter, [&gender, &iod]() { gender(iod); });
tpool.submit(&waiter, [&gender, &iod]() { gender(iod); }, true);
}
waiter.wait();
waiter.wait(&tpool);

auto geniod = [&](const cryptonote::transaction &tx, size_t n_vouts, size_t txidx) {
for (size_t k = 0; k < n_vouts; ++k)
Expand Down Expand Up @@ -1901,18 +1901,18 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
{
THROW_WALLET_EXCEPTION_IF(txidx >= tx_cache_data.size(), error::wallet_internal_error, "txidx out of range");
const size_t n_vouts = m_refresh_type == RefreshType::RefreshOptimizeCoinbase ? 1 : parsed_blocks[i].block.miner_tx.vout.size();
tpool.submit(&waiter, [&, i, txidx](){ geniod(parsed_blocks[i].block.miner_tx, n_vouts, txidx); });
tpool.submit(&waiter, [&, i, txidx](){ geniod(parsed_blocks[i].block.miner_tx, n_vouts, txidx); }, true);
}
++txidx;
for (size_t j = 0; j < parsed_blocks[i].txes.size(); ++j)
{
THROW_WALLET_EXCEPTION_IF(txidx >= tx_cache_data.size(), error::wallet_internal_error, "txidx out of range");
tpool.submit(&waiter, [&, i, j, txidx](){ geniod(parsed_blocks[i].txes[j], parsed_blocks[i].txes[j].vout.size(), txidx); });
tpool.submit(&waiter, [&, i, j, txidx](){ geniod(parsed_blocks[i].txes[j], parsed_blocks[i].txes[j].vout.size(), txidx); }, true);
++txidx;
}
}
THROW_WALLET_EXCEPTION_IF(txidx != tx_cache_data.size(), error::wallet_internal_error, "txidx did not reach expected value");
waiter.wait();
waiter.wait(&tpool);
hwdev.set_mode(hw::device::NONE);

size_t tx_cache_data_offset = 0;
Expand Down Expand Up @@ -1985,9 +1985,9 @@ void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks
for (size_t i = 0; i < blocks.size(); ++i)
{
tpool.submit(&waiter, boost::bind(&wallet2::parse_block_round, this, std::cref(blocks[i].block),
std::ref(parsed_blocks[i].block), std::ref(parsed_blocks[i].hash), std::ref(parsed_blocks[i].error)));
std::ref(parsed_blocks[i].block), std::ref(parsed_blocks[i].hash), std::ref(parsed_blocks[i].error)), true);
}
waiter.wait();
waiter.wait(&tpool);
for (size_t i = 0; i < blocks.size(); ++i)
{
if (parsed_blocks[i].error)
Expand All @@ -2010,10 +2010,10 @@ void wallet2::pull_and_parse_next_blocks(uint64_t start_height, uint64_t &blocks
boost::unique_lock<boost::mutex> lock(error_lock);
error = true;
}
});
}, true);
}
}
waiter.wait();
waiter.wait(&tpool);
}
catch(...)
{
Expand Down Expand Up @@ -2448,7 +2448,7 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
process_parsed_blocks(blocks_start_height, blocks, parsed_blocks, added_blocks);
blocks_fetched += added_blocks;
}
waiter.wait();
waiter.wait(&tpool);
if(!first && blocks_start_height == next_blocks_start_height)
{
m_node_rpc_proxy.set_height(m_blockchain.size());
Expand All @@ -2471,7 +2471,7 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
catch (const std::exception&)
{
blocks_fetched += added_blocks;
waiter.wait();
waiter.wait(&tpool);
if(try_count < 3)
{
LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")...");
Expand Down
Loading

0 comments on commit f8d1247

Please sign in to comment.