Browse Source
Saves about 10% of application memory usage once the mempool warms up. Since the mempool is DynamicUsage-regulated, this will translate to a larger mempool in the same amount of space. Map value type: eliminate the vin index; no users of the map need to know which input of the transaction is spending the prevout. Map key type: replace the COutPoint with a pointer to a COutPoint. A COutPoint is 36 bytes, but each COutPoint is accessible from the same map entry's value. A trivial DereferencingComparator functor allows indirect map keys, but the resulting syntax is misleading: `map.find(&outpoint)`. Implement an indirectmap that acts as a wrapper to a map that uses a DereferencingComparator, supporting a syntax that accurately reflect the container's semantics: inserts and iterators use pointers since they store pointers and need them to remain constant and dereferenceable, but lookup functions take const references.0.13
Kaz Wesley
9 years ago
6 changed files with 96 additions and 41 deletions
@ -0,0 +1,52 @@ |
|||||||
|
#ifndef BITCOIN_INDIRECTMAP_H |
||||||
|
#define BITCOIN_INDIRECTMAP_H |
||||||
|
|
||||||
|
template <class T> |
||||||
|
struct DereferencingComparator { bool operator()(const T a, const T b) const { return *a < *b; } }; |
||||||
|
|
||||||
|
/* Map whose keys are pointers, but are compared by their dereferenced values.
|
||||||
|
* |
||||||
|
* Differs from a plain std::map<const K*, T, DereferencingComparator<K*> > in |
||||||
|
* that methods that take a key for comparison take a K rather than taking a K* |
||||||
|
* (taking a K* would be confusing, since it's the value rather than the address |
||||||
|
* of the object for comparison that matters due to the dereferencing comparator). |
||||||
|
* |
||||||
|
* Objects pointed to by keys must not be modified in any way that changes the |
||||||
|
* result of DereferencingComparator. |
||||||
|
*/ |
||||||
|
template <class K, class T> |
||||||
|
class indirectmap { |
||||||
|
private: |
||||||
|
typedef std::map<const K*, T, DereferencingComparator<const K*> > base; |
||||||
|
base m; |
||||||
|
public: |
||||||
|
typedef typename base::iterator iterator; |
||||||
|
typedef typename base::const_iterator const_iterator; |
||||||
|
typedef typename base::size_type size_type; |
||||||
|
typedef typename base::value_type value_type; |
||||||
|
|
||||||
|
// passthrough (pointer interface)
|
||||||
|
std::pair<iterator, bool> insert(const value_type& value) { return m.insert(value); } |
||||||
|
|
||||||
|
// pass address (value interface)
|
||||||
|
iterator find(const K& key) { return m.find(&key); } |
||||||
|
const_iterator find(const K& key) const { return m.find(&key); } |
||||||
|
iterator lower_bound(const K& key) { return m.lower_bound(&key); } |
||||||
|
const_iterator lower_bound(const K& key) const { return m.lower_bound(&key); } |
||||||
|
size_type erase(const K& key) { return m.erase(&key); } |
||||||
|
size_type count(const K& key) const { return m.count(&key); } |
||||||
|
|
||||||
|
// passthrough
|
||||||
|
bool empty() const { return m.empty(); } |
||||||
|
size_type size() const { return m.size(); } |
||||||
|
size_type max_size() const { return m.max_size(); } |
||||||
|
void clear() { m.clear(); } |
||||||
|
iterator begin() { return m.begin(); } |
||||||
|
iterator end() { return m.end(); } |
||||||
|
const_iterator begin() const { return m.begin(); } |
||||||
|
const_iterator end() const { return m.end(); } |
||||||
|
const_iterator cbegin() const { return m.cbegin(); } |
||||||
|
const_iterator cend() const { return m.cend(); } |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // BITCOIN_INDIRECTMAP_H
|
Loading…
Reference in new issue