diff --git a/src/bench/mempool_eviction.cpp b/src/bench/mempool_eviction.cpp --- a/src/bench/mempool_eviction.cpp +++ b/src/bench/mempool_eviction.cpp @@ -15,8 +15,8 @@ bool spendsCoinbase = false; unsigned int nSigChecks = 1; LockPoints lp; - pool.addUnchecked(std::make_shared( - tx, nFee, nTime, nHeight, spendsCoinbase, nSigChecks, lp)); + pool.addUnchecked(CTxMemPoolEntryRef::make(tx, nFee, nTime, nHeight, + spendsCoinbase, nSigChecks, lp)); } // Right now this is only testing eviction performance in an extremely small diff --git a/src/bench/mempool_stress.cpp b/src/bench/mempool_stress.cpp --- a/src/bench/mempool_stress.cpp +++ b/src/bench/mempool_stress.cpp @@ -18,7 +18,7 @@ bool spendsCoinbase = false; unsigned int sigChecks = 1; LockPoints lp; - pool.addUnchecked(std::make_shared( + pool.addUnchecked(CTxMemPoolEntryRef::make( tx, 1000 * SATOSHI, nTime, nHeight, spendsCoinbase, sigChecks, lp)); } diff --git a/src/bench/rpc_mempool.cpp b/src/bench/rpc_mempool.cpp --- a/src/bench/rpc_mempool.cpp +++ b/src/bench/rpc_mempool.cpp @@ -14,11 +14,10 @@ static void AddTx(const CTransactionRef &tx, const Amount &fee, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pool.cs) { LockPoints lp; - pool.addUnchecked( - std::make_shared(tx, fee, /* time */ 0, - /* height */ 1, - /* spendsCoinbase */ false, - /*_sigChecks=*/1, lp)); + pool.addUnchecked(CTxMemPoolEntryRef::make(tx, fee, /*time=*/0, + /*height=*/1, + /*spendsCoinbase=*/false, + /*_sigChecks=*/1, lp)); } static void RpcMempool(benchmark::Bench &bench) { diff --git a/src/rcu.h b/src/rcu.h --- a/src/rcu.h +++ b/src/rcu.h @@ -253,4 +253,13 @@ \ template friend class ::RCUPtr +/** Implement std::hash so RCUPtr can be used as a key for maps or sets */ +namespace std { +template struct hash> { + size_t operator()(const RCUPtr &ptr) const noexcept { + return hash()(ptr.get()); + } +}; +} // end namespace std + #endif // BITCOIN_RCU_H diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -432,7 +432,7 @@ CTxMemPoolEntry ret(tx, nFee, nTime, nHeight, spendsCoinbase, nSigChecks, LockPoints()); ret.SetEntryId(entryId); - return std::make_shared(std::move(ret)); + return CTxMemPoolEntryRef::make(std::move(ret)); } /** diff --git a/src/txmempool.h b/src/txmempool.h --- a/src/txmempool.h +++ b/src/txmempool.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -75,7 +76,7 @@ }; class CTxMemPoolEntry; -using CTxMemPoolEntryRef = std::shared_ptr; +using CTxMemPoolEntryRef = RCUPtr; /** \class CTxMemPoolEntry * @@ -121,13 +122,23 @@ //! Track the height and time at which tx was final LockPoints lockPoints; + IMPLEMENT_RCU_REFCOUNT(uint64_t); + public: CTxMemPoolEntry(const CTransactionRef &_tx, const Amount fee, int64_t time, unsigned int entry_height, bool spends_coinbase, int64_t sigchecks, LockPoints lp); CTxMemPoolEntry(const CTxMemPoolEntry &other) = delete; - CTxMemPoolEntry(CTxMemPoolEntry &&other) = default; + CTxMemPoolEntry(CTxMemPoolEntry &&other) + : entryId(other.entryId), tx(std::move(other.tx)), + m_parents(std::move(other.m_parents)), + m_children(std::move(other.m_children)), nFee(other.nFee), + nTxSize(other.nTxSize), nUsageSize(other.nUsageSize), + nTime(other.nTime), entryHeight(other.entryHeight), + spendsCoinbase(other.spendsCoinbase), sigChecks(other.sigChecks), + feeDelta(other.feeDelta), lockPoints(std::move(other.lockPoints)), + refcount(other.refcount.load()){}; uint64_t GetEntryId() const { return entryId; } //! This should only be set by addUnchecked() before entry insertion into @@ -456,7 +467,7 @@ // addUnchecked must update state for all parents of a given transaction, // updating child links as necessary. - void addUnchecked(const CTxMemPoolEntryRef &entry) + void addUnchecked(CTxMemPoolEntryRef entry) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main); void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -176,7 +176,7 @@ nTransactionsUpdated += n; } -void CTxMemPool::addUnchecked(const CTxMemPoolEntryRef &entry) { +void CTxMemPool::addUnchecked(CTxMemPoolEntryRef entry) { // get a guaranteed unique id (in case tests re-use the same object) entry->SetEntryId(nextEntryId++); diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -726,7 +726,8 @@ const bool bypass_limits = args.m_bypass_limits; // Store transaction in memory - CTxMemPoolEntryRef entry = std::shared_ptr(std::move(ws.m_entry)); + CTxMemPoolEntry *pentry = ws.m_entry.release(); + auto entry = CTxMemPoolEntryRef::acquire(pentry); m_pool.addUnchecked(entry); // Trim mempool and check if tx was trimmed.