Use ModifyCoins instead of mutable GetCoins.
Replace the mutable non-copying GetCoins method with a ModifyCoins, which returns an encapsulated iterator, so we can keep track of concurrent modifications (as iterators can be invalidated by those) and run cleanup code after a modification is finished. This also removes the overloading of the 'GetCoins' name.
This commit is contained in:
49
src/coins.h
49
src/coins.h
@@ -83,11 +83,26 @@ public:
|
||||
// as new tx version will probably only be introduced at certain heights
|
||||
int nVersion;
|
||||
|
||||
// construct a CCoins from a CTransaction, at a given height
|
||||
CCoins(const CTransaction &tx, int nHeightIn) : fCoinBase(tx.IsCoinBase()), vout(tx.vout), nHeight(nHeightIn), nVersion(tx.nVersion) {
|
||||
void FromTx(const CTransaction &tx, int nHeightIn) {
|
||||
fCoinBase = tx.IsCoinBase();
|
||||
vout = tx.vout;
|
||||
nHeight = nHeightIn;
|
||||
nVersion = tx.nVersion;
|
||||
ClearUnspendable();
|
||||
}
|
||||
|
||||
// construct a CCoins from a CTransaction, at a given height
|
||||
CCoins(const CTransaction &tx, int nHeightIn) {
|
||||
FromTx(tx, nHeightIn);
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
fCoinBase = false;
|
||||
std::vector<CTxOut>().swap(vout);
|
||||
nHeight = 0;
|
||||
nVersion = 0;
|
||||
}
|
||||
|
||||
// empty constructor
|
||||
CCoins() : fCoinBase(false), vout(0), nHeight(0), nVersion(0) { }
|
||||
|
||||
@@ -323,10 +338,31 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class CCoinsViewCache;
|
||||
|
||||
/** A reference to a mutable cache entry. Encapsulating it allows us to run
|
||||
* cleanup code after the modification is finished, and keeping track of
|
||||
* concurrent modifications. */
|
||||
class CCoinsModifier
|
||||
{
|
||||
private:
|
||||
CCoinsViewCache& cache;
|
||||
CCoinsMap::iterator it;
|
||||
CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_);
|
||||
|
||||
public:
|
||||
CCoins* operator->() { return &it->second; }
|
||||
CCoins& operator*() { return it->second; }
|
||||
~CCoinsModifier();
|
||||
friend class CCoinsViewCache;
|
||||
};
|
||||
|
||||
/** CCoinsView that adds a memory cache for transactions to another CCoinsView */
|
||||
class CCoinsViewCache : public CCoinsViewBacked
|
||||
{
|
||||
protected:
|
||||
/* Whether this cache has an active modifier. */
|
||||
bool hasModifier;
|
||||
|
||||
/* Make mutable so that we can "fill the cache" even from Get-methods
|
||||
declared as "const". */
|
||||
@@ -335,6 +371,7 @@ protected:
|
||||
|
||||
public:
|
||||
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
|
||||
~CCoinsViewCache();
|
||||
|
||||
// Standard CCoinsView methods
|
||||
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||
@@ -349,8 +386,10 @@ public:
|
||||
// allowed while accessing the returned pointer.
|
||||
const CCoins* AccessCoins(const uint256 &txid) const;
|
||||
|
||||
// Return a modifiable reference to a CCoins. Check HaveCoins first.
|
||||
CCoins &GetCoins(const uint256 &txid);
|
||||
// Return a modifiable reference to a CCoins. If no entry with the given
|
||||
// txid exists, a new one is created. Simultaneous modifications are not
|
||||
// allowed.
|
||||
CCoinsModifier ModifyCoins(const uint256 &txid);
|
||||
|
||||
// Push the modifications applied to this cache to its base.
|
||||
// Failure to call this method before destruction will cause the changes to be forgotten.
|
||||
@@ -377,6 +416,8 @@ public:
|
||||
|
||||
const CTxOut &GetOutputFor(const CTxIn& input) const;
|
||||
|
||||
friend class CCoinsModifier;
|
||||
|
||||
private:
|
||||
CCoinsMap::iterator FetchCoins(const uint256 &txid);
|
||||
CCoinsMap::const_iterator FetchCoins(const uint256 &txid) const;
|
||||
|
||||
Reference in New Issue
Block a user