mirror of https://github.com/CGAL/cgal
Possibility to specify a custom allocator for Unique_hash_map and chained_map
This commit is contained in:
parent
11fdd71222
commit
60123e1678
|
|
@ -28,18 +28,18 @@ namespace CGAL {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename T> class chained_map;
|
template <typename T, typename Allocator = std::allocator<T> > class chained_map;
|
||||||
template <typename T> class chained_map_elem;
|
template <typename T> class chained_map_elem;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class chained_map_elem
|
class chained_map_elem
|
||||||
{
|
{
|
||||||
friend class chained_map<T>;
|
template<typename T2, typename Alloc> friend class chained_map;
|
||||||
std::size_t k; T i;
|
std::size_t k; T i;
|
||||||
chained_map_elem<T>* succ;
|
chained_map_elem<T>* succ;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
class chained_map
|
class chained_map
|
||||||
{
|
{
|
||||||
const std::size_t NULLKEY;
|
const std::size_t NULLKEY;
|
||||||
|
|
@ -50,8 +50,8 @@ class chained_map
|
||||||
chained_map_elem<T>* table;
|
chained_map_elem<T>* table;
|
||||||
chained_map_elem<T>* table_end;
|
chained_map_elem<T>* table_end;
|
||||||
chained_map_elem<T>* free;
|
chained_map_elem<T>* free;
|
||||||
std::size_t table_size;
|
std::size_t table_size;
|
||||||
std::size_t table_size_1;
|
std::size_t table_size_1;
|
||||||
|
|
||||||
chained_map_elem<T>* old_table;
|
chained_map_elem<T>* old_table;
|
||||||
chained_map_elem<T>* old_table_end;
|
chained_map_elem<T>* old_table_end;
|
||||||
|
|
@ -61,6 +61,9 @@ class chained_map
|
||||||
|
|
||||||
std::size_t old_index;
|
std::size_t old_index;
|
||||||
|
|
||||||
|
typedef typename Allocator::template rebind<chained_map_elem<T> >::other allocator_type;
|
||||||
|
allocator_type alloc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
T& xdef() { return STOP.i; }
|
T& xdef() { return STOP.i; }
|
||||||
const T& cxdef() const { return STOP.i; }
|
const T& cxdef() const { return STOP.i; }
|
||||||
|
|
@ -84,14 +87,25 @@ public:
|
||||||
std::size_t index(chained_map_item it) const { return it->k; }
|
std::size_t index(chained_map_item it) const { return it->k; }
|
||||||
T& inf(chained_map_item it) const { return it->i; }
|
T& inf(chained_map_item it) const { return it->i; }
|
||||||
|
|
||||||
chained_map(std::size_t n = 1);
|
chained_map(std::size_t n = 1);
|
||||||
chained_map(const chained_map<T>& D);
|
chained_map(const chained_map<T, Allocator>& D);
|
||||||
chained_map& operator=(const chained_map<T>& D);
|
chained_map& operator=(const chained_map<T, Allocator>& D);
|
||||||
|
|
||||||
|
|
||||||
void clear_entries();
|
void clear_entries();
|
||||||
void clear();
|
void clear();
|
||||||
~chained_map() { if (old_table) delete[] old_table; delete[] table; }
|
~chained_map()
|
||||||
|
{
|
||||||
|
if (old_table)
|
||||||
|
{
|
||||||
|
for (chained_map_item item = old_table ; item != old_table_end ; ++item)
|
||||||
|
alloc.destroy(item);
|
||||||
|
alloc.deallocate(old_table, old_table_end - old_table);
|
||||||
|
}
|
||||||
|
for (chained_map_item item = table ; item != table_end ; ++item)
|
||||||
|
alloc.destroy(item);
|
||||||
|
alloc.deallocate(table, table_end - table);
|
||||||
|
}
|
||||||
|
|
||||||
T& access(chained_map_item p, std::size_t x);
|
T& access(chained_map_item p, std::size_t x);
|
||||||
T& access(std::size_t x);
|
T& access(std::size_t x);
|
||||||
|
|
@ -101,8 +115,8 @@ public:
|
||||||
void statistics() const;
|
void statistics() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
inline T& chained_map<T>::access(std::size_t x)
|
inline T& chained_map<T, Allocator>::access(std::size_t x)
|
||||||
{ chained_map_item p = HASH(x);
|
{ chained_map_item p = HASH(x);
|
||||||
|
|
||||||
if (old_table) del_old_table();
|
if (old_table) del_old_table();
|
||||||
|
|
@ -121,12 +135,12 @@ inline T& chained_map<T>::access(std::size_t x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
void chained_map<T>::init_table(std::size_t t)
|
void chained_map<T, Allocator>::init_table(std::size_t t)
|
||||||
{
|
{
|
||||||
table_size = t;
|
table_size = t;
|
||||||
table_size_1 = t-1;
|
table_size_1 = t-1;
|
||||||
table = new chained_map_elem<T>[t + t/2];
|
table = alloc.allocate(t + t/2);
|
||||||
free = table + t;
|
free = table + t;
|
||||||
table_end = table + t + t/2;
|
table_end = table + t + t/2;
|
||||||
|
|
||||||
|
|
@ -138,8 +152,8 @@ void chained_map<T>::init_table(std::size_t t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
inline void chained_map<T>::insert(std::size_t x, T y)
|
inline void chained_map<T, Allocator>::insert(std::size_t x, T y)
|
||||||
{ chained_map_item q = HASH(x);
|
{ chained_map_item q = HASH(x);
|
||||||
if ( q->k == NULLKEY ) {
|
if ( q->k == NULLKEY ) {
|
||||||
q->k = x;
|
q->k = x;
|
||||||
|
|
@ -153,8 +167,8 @@ inline void chained_map<T>::insert(std::size_t x, T y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
void chained_map<T>::rehash()
|
void chained_map<T, Allocator>::rehash()
|
||||||
{
|
{
|
||||||
old_table = table;
|
old_table = table;
|
||||||
old_table_end = table_end;
|
old_table_end = table_end;
|
||||||
|
|
@ -185,8 +199,8 @@ void chained_map<T>::rehash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
void chained_map<T>::del_old_table()
|
void chained_map<T, Allocator>::del_old_table()
|
||||||
{
|
{
|
||||||
chained_map_item save_table = table;
|
chained_map_item save_table = table;
|
||||||
chained_map_item save_table_end = table_end;
|
chained_map_item save_table_end = table_end;
|
||||||
|
|
@ -204,7 +218,9 @@ void chained_map<T>::del_old_table()
|
||||||
|
|
||||||
T p = access(old_index);
|
T p = access(old_index);
|
||||||
|
|
||||||
delete[] table;
|
for (chained_map_item item = table ; item != table_end ; ++item)
|
||||||
|
alloc.destroy(item);
|
||||||
|
alloc.deallocate(table, table_end - table);
|
||||||
|
|
||||||
table = save_table;
|
table = save_table;
|
||||||
table_end = save_table_end;
|
table_end = save_table_end;
|
||||||
|
|
@ -214,8 +230,8 @@ void chained_map<T>::del_old_table()
|
||||||
access(old_index) = p;
|
access(old_index) = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
T& chained_map<T>::access(chained_map_item p, std::size_t x)
|
T& chained_map<T, Allocator>::access(chained_map_item p, std::size_t x)
|
||||||
{
|
{
|
||||||
STOP.k = x;
|
STOP.k = x;
|
||||||
chained_map_item q = p->succ;
|
chained_map_item q = p->succ;
|
||||||
|
|
@ -247,8 +263,8 @@ T& chained_map<T>::access(chained_map_item p, std::size_t x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
chained_map<T>::chained_map(std::size_t n) :
|
chained_map<T, Allocator>::chained_map(std::size_t n) :
|
||||||
NULLKEY(0), NONNULLKEY(1), old_table(0)
|
NULLKEY(0), NONNULLKEY(1), old_table(0)
|
||||||
{
|
{
|
||||||
if (n < 512)
|
if (n < 512)
|
||||||
|
|
@ -261,8 +277,8 @@ chained_map<T>::chained_map(std::size_t n) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
chained_map<T>::chained_map(const chained_map<T>& D) :
|
chained_map<T, Allocator>::chained_map(const chained_map<T, Allocator>& D) :
|
||||||
NULLKEY(0), NONNULLKEY(1), old_table(0)
|
NULLKEY(0), NONNULLKEY(1), old_table(0)
|
||||||
{
|
{
|
||||||
init_table(D.table_size);
|
init_table(D.table_size);
|
||||||
|
|
@ -276,11 +292,15 @@ chained_map<T>::chained_map(const chained_map<T>& D) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
chained_map<T>& chained_map<T>::operator=(const chained_map<T>& D)
|
chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(const chained_map<T, Allocator>& D)
|
||||||
{
|
{
|
||||||
clear_entries();
|
clear_entries();
|
||||||
delete[] table;
|
|
||||||
|
for (chained_map_item item = table ; item != table_end ; ++item)
|
||||||
|
alloc.destroy(item);
|
||||||
|
alloc.deallocate(table, table_end - table);
|
||||||
|
|
||||||
init_table(D.table_size);
|
init_table(D.table_size);
|
||||||
STOP.i = D.STOP.i; // xdef
|
STOP.i = D.STOP.i; // xdef
|
||||||
|
|
||||||
|
|
@ -293,23 +313,28 @@ chained_map<T>& chained_map<T>::operator=(const chained_map<T>& D)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
void chained_map<T>::clear_entries()
|
void chained_map<T, Allocator>::clear_entries()
|
||||||
{ for(chained_map_item p = table + 1; p < free; p++)
|
{ for(chained_map_item p = table + 1; p < free; p++)
|
||||||
if (p->k != NULLKEY || p >= table + table_size)
|
if (p->k != NULLKEY || p >= table + table_size)
|
||||||
p->i = T();
|
p->i = T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
void chained_map<T>::clear()
|
void chained_map<T, Allocator>::clear()
|
||||||
{ clear_entries();
|
{
|
||||||
delete[] table;
|
clear_entries();
|
||||||
|
|
||||||
|
for (chained_map_item item = table ; item != table_end ; ++item)
|
||||||
|
alloc.destroy(item);
|
||||||
|
alloc.deallocate(table, table_end - table);
|
||||||
|
|
||||||
init_table(512);
|
init_table(512);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
typename chained_map<T>::chained_map_item
|
typename chained_map<T, Allocator>::chained_map_item
|
||||||
chained_map<T>::lookup(std::size_t x) const
|
chained_map<T, Allocator>::lookup(std::size_t x) const
|
||||||
{ chained_map_item p = HASH(x);
|
{ chained_map_item p = HASH(x);
|
||||||
((std::size_t &)STOP.k) = x; // cast away const
|
((std::size_t &)STOP.k) = x; // cast away const
|
||||||
while (p->k != x)
|
while (p->k != x)
|
||||||
|
|
@ -318,21 +343,21 @@ chained_map<T>::lookup(std::size_t x) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
typename chained_map<T>::chained_map_item
|
typename chained_map<T, Allocator>::chained_map_item
|
||||||
chained_map<T>::first_item() const
|
chained_map<T, Allocator>::first_item() const
|
||||||
{ return next_item(table); }
|
{ return next_item(table); }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
typename chained_map<T>::chained_map_item
|
typename chained_map<T, Allocator>::chained_map_item
|
||||||
chained_map<T>::next_item(chained_map_item it) const
|
chained_map<T, Allocator>::next_item(chained_map_item it) const
|
||||||
{ if (it == 0) return 0;
|
{ if (it == 0) return 0;
|
||||||
do it++; while (it < table + table_size && it->k == NULLKEY);
|
do it++; while (it < table + table_size && it->k == NULLKEY);
|
||||||
return (it < free ? it : 0);
|
return (it < free ? it : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename Allocator>
|
||||||
void chained_map<T>::statistics() const
|
void chained_map<T, Allocator>::statistics() const
|
||||||
{ std::cout << "table_size: " << table_size <<"\n";
|
{ std::cout << "table_size: " << table_size <<"\n";
|
||||||
std::size_t n = 0;
|
std::size_t n = 0;
|
||||||
for (chained_map_item p = table + 1; p < table + table_size; p++)
|
for (chained_map_item p = table + 1; p < table + table_size; p++)
|
||||||
|
|
|
||||||
|
|
@ -34,22 +34,24 @@
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
template <class Key_, class Data_,
|
template <class Key_, class Data_,
|
||||||
class UniqueHashFunction = Handle_hash_function>
|
class UniqueHashFunction = Handle_hash_function,
|
||||||
|
class Allocator_ = std::allocator<Data_> >
|
||||||
class Unique_hash_map {
|
class Unique_hash_map {
|
||||||
public:
|
public:
|
||||||
typedef Key_ Key;
|
typedef Key_ Key;
|
||||||
typedef Data_ Data;
|
typedef Data_ Data;
|
||||||
typedef UniqueHashFunction Hash_function;
|
typedef UniqueHashFunction Hash_function;
|
||||||
|
typedef Allocator_ Allocator;
|
||||||
|
|
||||||
// STL compliance
|
// STL compliance
|
||||||
typedef Key_ key_type;
|
typedef Key_ key_type;
|
||||||
typedef Data_ data_type;
|
typedef Data_ data_type;
|
||||||
typedef UniqueHashFunction hasher;
|
typedef UniqueHashFunction hasher;
|
||||||
|
|
||||||
typedef Unique_hash_map<Key,Data,Hash_function> Self;
|
typedef Unique_hash_map<Key,Data,Hash_function,Allocator> Self;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef internal::chained_map<Data> Map;
|
typedef internal::chained_map<Data, Allocator> Map;
|
||||||
typedef typename Map::item Item;
|
typedef typename Map::item Item;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue