Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add _Alloc template parameters for FlatMap and FlatSet #2149

Merged
merged 2 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions src/butil/containers/flat_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ template <typename _K, typename _T,
// Test equivalence between stored-key and passed-key.
// stored-key is always on LHS, passed-key is always on RHS.
typename _Equal = DefaultEqualTo<_K>,
bool _Sparse = false>
bool _Sparse = false,
typename _Alloc = PtAllocator>
class FlatMap {
public:
typedef _K key_type;
typedef _T mapped_type;
typedef _Alloc allocator_type;
typedef FlatMapElement<_K, _T> Element;
typedef typename Element::value_type value_type;
typedef typename conditional<
Expand All @@ -148,7 +150,9 @@ class FlatMap {
key_type key;
};

FlatMap(const hasher& hashfn = hasher(), const key_equal& eql = key_equal());
FlatMap(const hasher& hashfn = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& alloc = allocator_type());
~FlatMap();
FlatMap(const FlatMap& rhs);
void operator=(const FlatMap& rhs);
Expand Down Expand Up @@ -265,6 +269,8 @@ class FlatMap {
char element_spaces[sizeof(Element)];
};

allocator_type& get_allocator() { return _pool.get_allocator(); }

private:
template <typename _Map, typename _Element> friend class FlatMapIterator;
template <typename _Map, typename _Element> friend class SparseFlatMapIterator;
Expand All @@ -279,26 +285,30 @@ template <typename _Map, typename _Element> friend class SparseFlatMapIterator;
u_int _load_factor;
hasher _hashfn;
key_equal _eql;
SingleThreadedPool<sizeof(Bucket), 1024, 16> _pool;
SingleThreadedPool<sizeof(Bucket), 1024, 16, allocator_type> _pool;
};

template <typename _K,
typename _Hash = DefaultHasher<_K>,
typename _Equal = DefaultEqualTo<_K>,
bool _Sparse = false>
bool _Sparse = false,
typename _Alloc = PtAllocator>
class FlatSet {
public:
typedef FlatMap<_K, FlatMapVoid, _Hash, _Equal, _Sparse> Map;
typedef FlatMap<_K, FlatMapVoid, _Hash, _Equal, _Sparse, _Alloc> Map;
typedef typename Map::key_type key_type;
typedef typename Map::value_type value_type;
typedef typename Map::Bucket Bucket;
typedef typename Map::iterator iterator;
typedef typename Map::const_iterator const_iterator;
typedef typename Map::hasher hasher;
typedef typename Map::key_equal key_equal;
typedef typename Map::allocator_type allocator_type;

FlatSet(const hasher& hashfn = hasher(), const key_equal& eql = key_equal())
: _map(hashfn, eql) {}
FlatSet(const hasher& hashfn = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& alloc = allocator_type())
: _map(hashfn, eql, alloc) {}
void swap(FlatSet & rhs) { _map.swap(rhs._map); }

int init(size_t nbucket, u_int load_factor = 80)
Expand Down
98 changes: 50 additions & 48 deletions src/butil/containers/flat_map_inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ template <typename Map, typename Value> class FlatMapIterator {
private:
friend class FlatMapIterator<Map, ConstValue>;
friend class FlatMap<typename Map::key_type, typename Map::mapped_type,
typename Map::hasher, typename Map::key_equal>;
typename Map::hasher, typename Map::key_equal,
false, typename Map::allocator_type>;

void find_and_set_valid_node() {
for (; !_entry->is_valid(); ++_entry);
Expand Down Expand Up @@ -222,30 +223,31 @@ friend class SparseFlatMapIterator<Map, ConstValue>;
};


template <typename _K, typename _T, typename _H, typename _E, bool _S>
FlatMap<_K, _T, _H, _E, _S>::FlatMap(const hasher& hashfn, const key_equal& eql)
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
FlatMap<_K, _T, _H, _E, _S, _A>::FlatMap(const hasher& hashfn, const key_equal& eql, const allocator_type& alloc)
: _size(0)
, _nbucket(0)
, _buckets(NULL)
, _thumbnail(NULL)
, _load_factor(0)
, _hashfn(hashfn)
, _eql(eql)
, _pool(alloc)
{}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
FlatMap<_K, _T, _H, _E, _S>::~FlatMap() {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
FlatMap<_K, _T, _H, _E, _S, _A>::~FlatMap() {
clear();
free(_buckets);
get_allocator().Free(_buckets);
_buckets = NULL;
free(_thumbnail);
_thumbnail = NULL;
_nbucket = 0;
_load_factor = 0;
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
FlatMap<_K, _T, _H, _E, _S>::FlatMap(const FlatMap& rhs)
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
FlatMap<_K, _T, _H, _E, _S, _A>::FlatMap(const FlatMap& rhs)
: _size(0)
, _nbucket(0)
, _buckets(NULL)
Expand All @@ -256,9 +258,9 @@ FlatMap<_K, _T, _H, _E, _S>::FlatMap(const FlatMap& rhs)
operator=(rhs);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
void
FlatMap<_K, _T, _H, _E, _S>::operator=(const FlatMap<_K, _T, _H, _E, _S>& rhs) {
FlatMap<_K, _T, _H, _E, _S, _A>::operator=(const FlatMap<_K, _T, _H, _E, _S, _A>& rhs) {
if (this == &rhs) {
return;
}
Expand All @@ -272,10 +274,10 @@ FlatMap<_K, _T, _H, _E, _S>::operator=(const FlatMap<_K, _T, _H, _E, _S>& rhs) {
_load_factor = rhs._load_factor;
}
if (_buckets == NULL || is_too_crowded(rhs._size)) {
free(_buckets);
get_allocator().Free(_buckets);
_nbucket = rhs._nbucket;
// note: need an extra bucket to let iterator know where buckets end
_buckets = (Bucket*)malloc(sizeof(Bucket) * (_nbucket + 1/*note*/));
_buckets = (Bucket*)get_allocator().Alloc(sizeof(Bucket) * (_nbucket + 1/*note*/));
if (NULL == _buckets) {
LOG(ERROR) << "Fail to new _buckets";
return;
Expand Down Expand Up @@ -320,8 +322,8 @@ FlatMap<_K, _T, _H, _E, _S>::operator=(const FlatMap<_K, _T, _H, _E, _S>& rhs) {
}
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
int FlatMap<_K, _T, _H, _E, _S>::init(size_t nbucket, u_int load_factor) {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
int FlatMap<_K, _T, _H, _E, _S, _A>::init(size_t nbucket, u_int load_factor) {
if (initialized()) {
LOG(ERROR) << "Already initialized";
return -1;
Expand All @@ -334,7 +336,7 @@ int FlatMap<_K, _T, _H, _E, _S>::init(size_t nbucket, u_int load_factor) {
_nbucket = flatmap_round(nbucket);
_load_factor = load_factor;

_buckets = (Bucket*)malloc(sizeof(Bucket) * (_nbucket + 1));
_buckets = (Bucket*)get_allocator().Alloc(sizeof(Bucket) * (_nbucket + 1));
if (NULL == _buckets) {
LOG(ERROR) << "Fail to new _buckets";
return -1;
Expand All @@ -355,8 +357,8 @@ int FlatMap<_K, _T, _H, _E, _S>::init(size_t nbucket, u_int load_factor) {
return 0;
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
void FlatMap<_K, _T, _H, _E, _S>::swap(FlatMap<_K, _T, _H, _E, _S> & rhs) {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
void FlatMap<_K, _T, _H, _E, _S, _A>::swap(FlatMap<_K, _T, _H, _E, _S, _A> & rhs) {
std::swap(rhs._size, _size);
std::swap(rhs._nbucket, _nbucket);
std::swap(rhs._buckets, _buckets);
Expand All @@ -367,22 +369,22 @@ void FlatMap<_K, _T, _H, _E, _S>::swap(FlatMap<_K, _T, _H, _E, _S> & rhs) {
rhs._pool.swap(_pool);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
_T* FlatMap<_K, _T, _H, _E, _S>::insert(const key_type& key,
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
_T* FlatMap<_K, _T, _H, _E, _S, _A>::insert(const key_type& key,
const mapped_type& value) {
mapped_type *p = &operator[](key);
*p = value;
return p;
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
_T* FlatMap<_K, _T, _H, _E, _S>::insert(const std::pair<key_type, mapped_type>& kv) {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
_T* FlatMap<_K, _T, _H, _E, _S, _A>::insert(const std::pair<key_type, mapped_type>& kv) {
return insert(kv.first, kv.second);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
template <typename K2>
size_t FlatMap<_K, _T, _H, _E, _S>::erase(const K2& key, _T* old_value) {
size_t FlatMap<_K, _T, _H, _E, _S, _A>::erase(const K2& key, _T* old_value) {
if (!initialized()) {
return 0;
}
Expand Down Expand Up @@ -446,8 +448,8 @@ size_t FlatMap<_K, _T, _H, _E, _S>::erase(const K2& key, _T* old_value) {
return 0;
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
void FlatMap<_K, _T, _H, _E, _S>::clear() {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
void FlatMap<_K, _T, _H, _E, _S, _A>::clear() {
if (0 == _size) {
return;
}
Expand All @@ -473,15 +475,15 @@ void FlatMap<_K, _T, _H, _E, _S>::clear() {
}
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
void FlatMap<_K, _T, _H, _E, _S>::clear_and_reset_pool() {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
void FlatMap<_K, _T, _H, _E, _S, _A>::clear_and_reset_pool() {
clear();
_pool.reset();
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
template <typename K2>
_T* FlatMap<_K, _T, _H, _E, _S>::seek(const K2& key) const {
_T* FlatMap<_K, _T, _H, _E, _S, _A>::seek(const K2& key) const {
if (!initialized()) {
return NULL;
}
Expand All @@ -502,8 +504,8 @@ _T* FlatMap<_K, _T, _H, _E, _S>::seek(const K2& key) const {
return NULL;
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
_T& FlatMap<_K, _T, _H, _E, _S>::operator[](const key_type& key) {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
_T& FlatMap<_K, _T, _H, _E, _S, _A>::operator[](const key_type& key) {
const size_t index = flatmap_mod(_hashfn(key), _nbucket);
Bucket& first_node = _buckets[index];
if (!first_node.is_valid()) {
Expand Down Expand Up @@ -550,8 +552,8 @@ _T& FlatMap<_K, _T, _H, _E, _S>::operator[](const key_type& key) {
}
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
void FlatMap<_K, _T, _H, _E, _S>::save_iterator(
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
void FlatMap<_K, _T, _H, _E, _S, _A>::save_iterator(
const const_iterator& it, PositionHint* hint) const {
hint->nbucket = _nbucket;
hint->offset = it._entry - _buckets;
Expand All @@ -564,9 +566,9 @@ void FlatMap<_K, _T, _H, _E, _S>::save_iterator(
}
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
typename FlatMap<_K, _T, _H, _E, _S>::const_iterator
FlatMap<_K, _T, _H, _E, _S>::restore_iterator(const PositionHint& hint) const {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
typename FlatMap<_K, _T, _H, _E, _S, _A>::const_iterator
FlatMap<_K, _T, _H, _E, _S, _A>::restore_iterator(const PositionHint& hint) const {
if (hint.nbucket != _nbucket) // resized
return begin(); // restart

Expand Down Expand Up @@ -598,8 +600,8 @@ FlatMap<_K, _T, _H, _E, _S>::restore_iterator(const PositionHint& hint) const {
return const_iterator(this, hint.offset);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
bool FlatMap<_K, _T, _H, _E, _S>::resize(size_t nbucket2) {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
bool FlatMap<_K, _T, _H, _E, _S, _A>::resize(size_t nbucket2) {
nbucket2 = flatmap_round(nbucket2);
if (_nbucket == nbucket2) {
return false;
Expand All @@ -622,8 +624,8 @@ bool FlatMap<_K, _T, _H, _E, _S>::resize(size_t nbucket2) {
return true;
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
BucketInfo FlatMap<_K, _T, _H, _E, _S>::bucket_info() const {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
BucketInfo FlatMap<_K, _T, _H, _E, _S, _A>::bucket_info() const {
size_t max_n = 0;
size_t nentry = 0;
for (size_t i = 0; i < _nbucket; ++i) {
Expand All @@ -643,23 +645,23 @@ inline std::ostream& operator<<(std::ostream& os, const BucketInfo& info) {
<< " avgb=" << info.average_length << '}';
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
typename FlatMap<_K, _T, _H, _E, _S>::iterator FlatMap<_K, _T, _H, _E, _S>::begin() {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
typename FlatMap<_K, _T, _H, _E, _S, _A>::iterator FlatMap<_K, _T, _H, _E, _S, _A>::begin() {
return iterator(this, 0);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
typename FlatMap<_K, _T, _H, _E, _S>::iterator FlatMap<_K, _T, _H, _E, _S>::end() {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
typename FlatMap<_K, _T, _H, _E, _S, _A>::iterator FlatMap<_K, _T, _H, _E, _S, _A>::end() {
return iterator(this, _nbucket);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
typename FlatMap<_K, _T, _H, _E, _S>::const_iterator FlatMap<_K, _T, _H, _E, _S>::begin() const {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
typename FlatMap<_K, _T, _H, _E, _S, _A>::const_iterator FlatMap<_K, _T, _H, _E, _S, _A>::begin() const {
return const_iterator(this, 0);
}

template <typename _K, typename _T, typename _H, typename _E, bool _S>
typename FlatMap<_K, _T, _H, _E, _S>::const_iterator FlatMap<_K, _T, _H, _E, _S>::end() const {
template <typename _K, typename _T, typename _H, typename _E, bool _S, typename _A>
typename FlatMap<_K, _T, _H, _E, _S, _A>::const_iterator FlatMap<_K, _T, _H, _E, _S, _A>::end() const {
return const_iterator(this, _nbucket);
}

Expand Down
19 changes: 15 additions & 4 deletions src/butil/single_threaded_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@ namespace butil {
// void* mem = pool.get();
// pool.back(mem);

class PtAllocator {
public:
void* Alloc(size_t n) { return malloc(n); }
void Free(void* p) { free(p); }
};

template <size_t ITEM_SIZE_IN, // size of an item
size_t BLOCK_SIZE_IN, // suggested size of a block
size_t MIN_NITEM = 1> // minimum number of items in one block
size_t MIN_NITEM = 1,
typename Allocator = PtAllocator> // minimum number of items in one block
class SingleThreadedPool {
public:
// Note: this is a union. The next pointer is set iff when spaces is free,
Expand All @@ -54,7 +61,8 @@ class SingleThreadedPool {
static const size_t NITEM = Block::NITEM;
static const size_t ITEM_SIZE = ITEM_SIZE_IN;

SingleThreadedPool() : _free_nodes(NULL), _blocks(NULL) {}
SingleThreadedPool(const Allocator& alloc = Allocator())
: _free_nodes(NULL), _blocks(NULL), _allocator(alloc) {}
~SingleThreadedPool() { reset(); }

void swap(SingleThreadedPool & other) {
Expand All @@ -71,7 +79,7 @@ class SingleThreadedPool {
return spaces;
}
if (_blocks == NULL || _blocks->nalloc >= Block::NITEM) {
Block* new_block = (Block*)malloc(sizeof(Block));
Block* new_block = (Block*)_allocator.Alloc(sizeof(Block));
if (new_block == NULL) {
return NULL;
}
Expand All @@ -98,7 +106,7 @@ class SingleThreadedPool {
_free_nodes = NULL;
while (_blocks) {
Block* next = _blocks->next;
free(_blocks);
_allocator.Free(_blocks);
_blocks = next;
}
}
Expand All @@ -122,13 +130,16 @@ class SingleThreadedPool {
return count_allocated() - count_free();
}

Allocator& get_allocator() { return _allocator; }

private:
// You should not copy a pool.
SingleThreadedPool(const SingleThreadedPool&);
void operator=(const SingleThreadedPool&);

Node* _free_nodes;
Block* _blocks;
Allocator _allocator;
};

} // namespace butil
Expand Down