remove the raise_exeception member variable from the memory manager.

changed the allocate(), reallocate(), callocate() to accept raise_exception instead.
touched up HashTable a bit
This commit is contained in:
hyung-hwan 2015-02-17 04:45:20 +00:00
parent 0a5ee4de4d
commit 8c15d39d9a
11 changed files with 161 additions and 149 deletions

View File

@ -24,8 +24,8 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef _QSE_CMN_PAIR_HPP_ #ifndef _QSE_CMN_COUPLE_HPP_
#define _QSE_CMN_PAIR_HPP_ #define _QSE_CMN_COUPLE_HPP_
#include <qse/types.h> #include <qse/types.h>
#include <qse/macros.h> #include <qse/macros.h>
@ -34,15 +34,15 @@
QSE_BEGIN_NAMESPACE(QSE) QSE_BEGIN_NAMESPACE(QSE)
///////////////////////////////// /////////////////////////////////
template <typename KEY, typename VALUE> class Pair template <typename KEY, typename VALUE> class Couple
{ {
public: public:
KEY key; KEY key;
VALUE value; VALUE value;
Pair () {} Couple () {}
Pair (const KEY& key): key (key) {} Couple (const KEY& key): key (key) {}
Pair (const KEY& key, const VALUE& value): key (key), value (value) {} Couple (const KEY& key, const VALUE& value): key (key), value (value) {}
KEY& getKey () { return this->key; } KEY& getKey () { return this->key; }
const KEY& getKey () const { return this->key; } const KEY& getKey () const { return this->key; }

View File

@ -126,10 +126,6 @@ public:
this->load_factor = load_factor; this->load_factor = load_factor;
this->threshold = node_capacity * load_factor / 100; this->threshold = node_capacity * load_factor / 100;
// the memory manager for the linked list must raise an exception
// upon memory allocation error.
QSE_ASSERT (this->getMmgr()->isExceptionRaising());
} }
HashList (const SelfType& list): Mmged (list) HashList (const SelfType& list): Mmged (list)

View File

@ -29,7 +29,7 @@
#include <qse/Hashable.hpp> #include <qse/Hashable.hpp>
#include <qse/cmn/LinkedList.hpp> #include <qse/cmn/LinkedList.hpp>
#include <qse/cmn/Pair.hpp> #include <qse/cmn/Couple.hpp>
///////////////////////////////// /////////////////////////////////
QSE_BEGIN_NAMESPACE(QSE) QSE_BEGIN_NAMESPACE(QSE)
@ -47,6 +47,7 @@ struct HashTableHasher
template<typename T> template<typename T>
struct HashTableComparator struct HashTableComparator
{ {
// it must return true if two values are equal
bool operator() (const T& v1, const T& v2) const bool operator() (const T& v1, const T& v2) const
{ {
return v1 == v2; return v1 == v2;
@ -69,8 +70,8 @@ template <typename K, typename V, typename HASHER = HashTableHasher<K>, typename
class HashTable: public Mmged class HashTable: public Mmged
{ {
public: public:
typedef Pair<K,V> Entry; typedef Couple<K,V> Pair;
typedef LinkedList<Entry> Bucket; typedef LinkedList<Pair> Bucket;
typedef HashTable<K,V,HASHER,COMPARATOR,RESIZER> SelfType; typedef HashTable<K,V,HASHER,COMPARATOR,RESIZER> SelfType;
protected: protected:
@ -127,18 +128,18 @@ public:
{ {
this->buckets = this->allocate_bucket (this->getMmgr(), bucket_size); this->buckets = this->allocate_bucket (this->getMmgr(), bucket_size);
this->bucket_size = bucket_size; this->bucket_size = bucket_size;
this->entry_count = 0; this->pair_count = 0;
this->load_factor = load_factor; this->load_factor = load_factor;
this->threshold = bucket_size * load_factor / 100; this->threshold = bucket_size * load_factor / 100;
} }
HashTable (const SelfType& table): Mmged (table) HashTable (const SelfType& table): Mmged (table)
{ {
this->buckets = this->allocate_bucket (this->getMmgr(), table.bucket_size); this->buckets = this->allocate_bucket (this->getMmgr(), table.bucket_size);
this->bucket_size = table.bucket_size; this->bucket_size = table.bucket_size;
this->entry_count = 0; this->pair_count = 0;
this->load_factor = table.load_factor; this->load_factor = table.load_factor;
this->threshold = table.bucket_size * table.load_factor / 100; this->threshold = table.bucket_size * table.load_factor / 100;
for (qse_size_t i = 0; i < table.bucket_size; i++) for (qse_size_t i = 0; i < table.bucket_size; i++)
{ {
@ -146,15 +147,15 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = b->getHeadNode(); np; np = np->getNext()) for (np = b->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
qse_size_t hc = this->hasher(e.key) % this->bucket_size; qse_size_t hc = this->hasher(e.key) % this->bucket_size;
this->buckets[hc]->append (e); this->buckets[hc]->append (e);
this->entry_count++; this->pair_count++;
} }
} }
// doesn't need to rehash in the copy constructor. // no rehashing is needed in the copy constructor.
//if (entry_count >= threshold) this->rehash (); //if (this->pair_count >= threshold) this->rehash ();
} }
~HashTable () ~HashTable ()
@ -173,33 +174,45 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = b->getHeadNode(); np; np = np->getNext()) for (np = b->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
qse_size_t hc = this->hasher(e.key) % this->bucket_size; qse_size_t hc = this->hasher(e.key) % this->bucket_size;
this->buckets[hc]->append (e); this->buckets[hc]->append (e);
entry_count++; this->pair_count++;
} }
} }
if (this->entry_count >= this->threshold) this->rehash (); if (this->pair_count >= this->threshold) this->rehash ();
return *this; return *this;
} }
qse_size_t getSize () const qse_size_t getSize () const
{ {
return this->entry_count; return this->pair_count;
} }
bool isEmpty () const bool isEmpty () const
{ {
return this->entry_count == 0; return this->pair_count == 0;
} }
/// The getBucketSize() function returns the number of
/// pair list currently existing.
qse_size_t getBucketSize () const qse_size_t getBucketSize () const
{ {
return this->bucket_size; return this->bucket_size;
} }
Bucket& getBucket (qse_size_t index) const /// The getBucket() function returns the pointer to the
/// list of pairs of the given hash value \a index.
Bucket* getBucket (qse_size_t index)
{
QSE_ASSERT (index < this->bucket_size);
return this->buckets[index];
}
/// The getBucket() function returns the pointer to the
/// list of pairs of the given hash value \a index.
const Bucket* getBucket (qse_size_t index) const
{ {
QSE_ASSERT (index < this->bucket_size); QSE_ASSERT (index < this->bucket_size);
return this->buckets[index]; return this->buckets[index];
@ -213,19 +226,19 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (this->comparator (key, e.key)) return e.value; if (this->comparator (key, e.key)) return e.value;
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
// insert a new key if the key is not found // insert a new key if the key is not found
Entry& e2 = this->buckets[hc]->append (Entry(key)); Pair& e2 = this->buckets[hc]->append (Pair(key));
entry_count++; this->pair_count++;
return e2.value; return e2.value;
} }
@ -233,62 +246,80 @@ public:
{ {
qse_size_t hc = this->hasher(key) % this->bucket_size; qse_size_t hc = this->hasher(key) % this->bucket_size;
Entry* pair = this->find_pair (key, hc); Pair* pair = this->find_pair (key, hc);
if (pair) return pair->value; if (pair) return pair->value;
// insert a new key if the key is not found // insert a new key if the key is not found
Entry& new_pair = this->buckets[hc]->append (Entry(key)); Pair& new_pair = this->buckets[hc]->append (Pair(key));
this->entry_count++; this->pair_count++;
return new_pair.value; return new_pair.value;
} }
#endif #endif
// protected:
// NOTE: getConstWithCustomKey() and getWithCustomKey() would template <typename MK, typename MHASHER, typename MCOMPARATOR>
// not need to have different names if compilers were smarter. Pair* find_pair_with_custom_key (const MK& key) const
//
template <typename MK, typename MHASHER>
const V* getConstWithCustomKey (const MK& key) const
{ {
MHASHER h; MHASHER hash;
qse_size_t hc = h(key) % bucket_size; MCOMPARATOR is_equal;
qse_size_t hc = hash(key) % this->bucket_size;
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
const Entry& e = np->value; Pair& e = np->value;
if (key == e.key) return &e.value; if (is_equal(key, e.key)) return &e;
} }
return QSE_NULL; return QSE_NULL;
} }
template <typename MK, typename MHASHER> public:
V* getWithCustomKey (const MK& key) const /// \code
/// typedef QSE::HashTable<int,int,IntHasher> IntTable;
/// struct IntClass
/// {
/// IntClass (int x = 0): x (x) {}
/// int x;
/// };
/// struct IntClassHasher
/// {
/// qse_size_t operator() (const IntClass& v) const { return v.x; }
/// };
/// struct IntClassComparator
/// {
/// bool operator() (const IntClass& v, int y) const { return v.x == y; }
/// }
/// };
/// int main ()
/// {
/// IntTable int_list (NULL, 1000);
/// ...
/// IntTable::Pair* pair = int_list.findPairWithCustomKey<IntClass,IntClassHasher,IntClassComparator> (IntClass(50));
/// ...
/// }
/// \endcode
template <typename MK, typename MHASHER, typename MCOMPARATOR>
const Pair* findPairWithCustomKey (const MK& key) const
{ {
MHASHER h; return this->find_pair_with_custom_key<MK,MHASHER,MCOMPARATOR> (key);
qse_size_t hc = h(key) % bucket_size; }
typename Bucket::Node* np; template <typename MK, typename MHASHER, typename MCOMPARATOR>
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) Pair* findPairWithCustomKey (const MK& key)
{ {
Entry& e = np->value; return this->find_pair_with_custom_key<MK,MHASHER,MCOMPARATOR> (key);
if (key == e.key) return &e.value;
}
return QSE_NULL;
} }
protected: protected:
Entry* find_pair (const K& key, qse_size_t hc) Pair* find_pair (const K& key, qse_size_t hc)
{ {
//qse_size_t hc = this->hasher(key) % this->bucket_size;
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (this->comparator (key, e.key)) return &e; if (this->comparator (key, e.key)) return &e;
} }
@ -296,26 +327,26 @@ protected:
} }
public: public:
Entry* findPair (const K& key) Pair* findPair (const K& key)
{ {
return this->find_pair (key, this->hasher(key) % this->bucket_size); return this->find_pair (key, this->hasher(key) % this->bucket_size);
} }
const Entry* findPair (const K& key) const const Pair* findPair (const K& key) const
{ {
return this->find_pair (key, this->hasher(key) % this->bucket_size); return this->find_pair (key, this->hasher(key) % this->bucket_size);
} }
V* findValue (const K& key) V* findValue (const K& key)
{ {
Entry* pair = this->findPair (key); Pair* pair = this->findPair (key);
if (pair) return &pair->value; if (pair) return &pair->value;
return QSE_NULL; return QSE_NULL;
} }
const V* findValue (const K& key) const const V* findValue (const K& key) const
{ {
const Entry* pair = this->findPair (key); const Pair* pair = this->findPair (key);
if (pair) return &pair->value; if (pair) return &pair->value;
return QSE_NULL; return QSE_NULL;
} }
@ -327,7 +358,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (this->comparator (key, e.key)) if (this->comparator (key, e.key))
{ {
*hash_code = hc; *hash_code = hc;
@ -346,7 +377,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (this->comparator (key, e.key)) if (this->comparator (key, e.key))
{ {
*hash_code = hc; *hash_code = hc;
@ -360,104 +391,104 @@ public:
int put (const K& key, const V& value) int put (const K& key, const V& value)
{ {
upsert (key, value); this->upsert (key, value);
return 0; return 0;
} }
int putNew (const K& key, const V& value) int putNew (const K& key, const V& value)
{ {
return (insertNew(key,value) == QSE_NULL)? -1: 0; return (this->insertNew(key,value) == QSE_NULL)? -1: 0;
} }
Entry* insert (const K& key) Pair* insert (const K& key)
{ {
qse_size_t hc = this->hasher(key) % bucket_size; qse_size_t hc = this->hasher(key) % bucket_size;
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (this->comparator (key, e.key)) return &e; if (this->comparator (key, e.key)) return &e;
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
Entry& e = this->buckets[hc]->append (Entry(key)); Pair& e = this->buckets[hc]->append (Pair(key));
this->entry_count++; this->pair_count++;
return &e; return &e;
} }
Entry* insert (const K& key, const V& value) Pair* insert (const K& key, const V& value)
{ {
qse_size_t hc = this->hasher(key) % bucket_size; qse_size_t hc = this->hasher(key) % bucket_size;
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (this->comparator (key, e.key)) return &e; if (this->comparator (key, e.key)) return &e;
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
Entry& e = this->buckets[hc]->append (Entry(key,value)); Pair& e = this->buckets[hc]->append (Pair(key,value));
entry_count++; this->pair_count++;
return &e; return &e;
} }
#if 0 #if 0
Entry* upsert (const K& Key) Pair* upsert (const K& Key)
{ {
qse_size_t hc = this->hasher(key) % this->bucket_size; qse_size_t hc = this->hasher(key) % this->bucket_size;
Entry* pair = this->find_pair (key, hc); Pair* pair = this->find_pair (key, hc);
if (pair) if (pair)
{ {
// don't change the existing value. // don't change the existing value.
return pair return pair
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % this->bucket_size; hc = this->hasher(key) % this->bucket_size;
} }
// insert a new key if the key is not found // insert a new key if the key is not found
Entry& new_pair = this->buckets[hc]->append (Entry(key)); Pair& new_pair = this->buckets[hc]->append (Pair(key));
this->entry_count++; this->pair_count++;
return &new_pair return &new_pair
} }
#endif #endif
Entry* upsert (const K& key, const V& value) Pair* upsert (const K& key, const V& value)
{ {
qse_size_t hc = this->hasher(key) % this->bucket_size; qse_size_t hc = this->hasher(key) % this->bucket_size;
Entry* pair = this->find_pair (key, hc); Pair* pair = this->find_pair (key, hc);
if (pair) if (pair)
{ {
pair->value = value; pair->value = value;
return pair; return pair;
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % this->bucket_size; hc = this->hasher(key) % this->bucket_size;
} }
// insert a new key if the key is not found // insert a new key if the key is not found
Entry& new_pair = this->buckets[hc]->append (Entry(key,value)); Pair& new_pair = this->buckets[hc]->append (Pair(key,value));
this->entry_count++; this->pair_count++;
return &new_pair; return &new_pair;
/* /*
@ -466,7 +497,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (key == e.key) if (key == e.key)
{ {
e.value = value; e.value = value;
@ -474,14 +505,14 @@ public:
} }
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
Entry& e = this->buckets[hc]->append (Entry(key,value)); Pair& e = this->buckets[hc]->append (Pair(key,value));
this->entry_count++; this->pair_count++;
return &e.value; return &e.value;
*/ */
} }
@ -495,18 +526,18 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (key == e.key) return QSE_NULL; if (key == e.key) return QSE_NULL;
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
Entry& e = this->buckets[hc]->append (Entry(key)); Pair& e = this->buckets[hc]->append (Pair(key));
entry_count++; this->pair_count++;
return &e.value; return &e.value;
} }
@ -517,18 +548,18 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (key == e.key) return QSE_NULL; if (key == e.key) return QSE_NULL;
} }
if (entry_count >= threshold) if (this->pair_count >= threshold)
{ {
this->rehash (); this->rehash ();
hc = this->hasher(key) % bucket_size; hc = this->hasher(key) % bucket_size;
} }
Entry& e = this->buckets[hc]->append (Entry(key, value)); Pair& e = this->buckets[hc]->append (Pair(key, value));
entry_count++; this->pair_count++;
return &e.value; return &e.value;
} }
#endif #endif
@ -543,11 +574,11 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (key == e.key) if (key == e.key)
{ {
this->buckets[hc]->remove (np); this->buckets[hc]->remove (np);
this->entry_count--; this->pair_count--;
return 0; return 0;
} }
} }
@ -562,11 +593,11 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (key == e.key) if (key == e.key)
{ {
this->buckets[hc]->remove (np); this->buckets[hc]->remove (np);
this->entry_count--; this->pair_count--;
return 0; return 0;
} }
} }
@ -580,7 +611,7 @@ public:
// WARNING: this method should be used with extra care. // WARNING: this method should be used with extra care.
// //
this->buckets[hc]->remove (np); this->buckets[hc]->remove (np);
this->entry_count--; this->pair_count--;
return 0; return 0;
} }
@ -595,7 +626,7 @@ public:
np = this->buckets[i]->getHeadNode(); np = this->buckets[i]->getHeadNode();
while (np != QSE_NULL) while (np != QSE_NULL)
{ {
Entry& e = np->value; Pair& e = np->value;
np2 = np->getNext (); np2 = np->getNext ();
if (value == e.value) if (value == e.value)
{ {
@ -617,7 +648,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (key == e.key) return true; if (key == e.key) return true;
} }
@ -631,7 +662,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (value == e.value) return true; if (value == e.value) return true;
} }
} }
@ -642,7 +673,7 @@ public:
void clear (qse_size_t new_bucket_size = 0) void clear (qse_size_t new_bucket_size = 0)
{ {
for (qse_size_t i = 0; i < bucket_size; i++) this->buckets[i]->clear (); for (qse_size_t i = 0; i < bucket_size; i++) this->buckets[i]->clear ();
this->entry_count = 0; this->pair_count = 0;
if (new_bucket_size > 0) if (new_bucket_size > 0)
{ {
@ -656,7 +687,7 @@ public:
} }
typedef int (SelfType::*TraverseCallback) typedef int (SelfType::*TraverseCallback)
(const Entry& entry, void* user_data) const; (const Pair& entry, void* user_data) const;
int traverse (TraverseCallback callback, void* user_data) const int traverse (TraverseCallback callback, void* user_data) const
{ {
@ -665,7 +696,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
{ {
const Entry& e = np->value; const Pair& e = np->value;
if ((this->*callback)(e,user_data) == -1) return -1; if ((this->*callback)(e,user_data) == -1) return -1;
} }
} }
@ -674,7 +705,7 @@ public:
} }
typedef int (*StaticTraverseCallback) typedef int (*StaticTraverseCallback)
(SelfType* table, Entry& entry, void* user_data); (SelfType* table, Pair& entry, void* user_data);
int traverse (StaticTraverseCallback callback, void* user_data) int traverse (StaticTraverseCallback callback, void* user_data)
{ {
@ -683,7 +714,7 @@ public:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
{ {
Entry& e = np->value; Pair& e = np->value;
if (callback(this,e,user_data) == -1) return -1; if (callback(this,e,user_data) == -1) return -1;
} }
} }
@ -692,7 +723,7 @@ public:
} }
protected: protected:
mutable qse_size_t entry_count; mutable qse_size_t pair_count;
mutable qse_size_t bucket_size; mutable qse_size_t bucket_size;
mutable Bucket** buckets; mutable Bucket** buckets;
mutable qse_size_t threshold; mutable qse_size_t threshold;
@ -714,7 +745,7 @@ protected:
typename Bucket::Node* np; typename Bucket::Node* np;
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext()) for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
{ {
const Entry& e = np->value; const Pair& e = np->value;
qse_size_t hc = e.key.hashCode() % new_bucket_size; qse_size_t hc = e.key.hashCode() % new_bucket_size;
new_this->buckets[hc]->append (e); new_this->buckets[hc]->append (e);
} }
@ -729,7 +760,7 @@ protected:
while (np) while (np)
{ {
typename Bucket::Node* next = np->getNext(); typename Bucket::Node* next = np->getNext();
const Entry& e = np->value; const Pair& e = np->value;
qse_size_t hc = this->hasher(e.key) % new_bucket_size; qse_size_t hc = this->hasher(e.key) % new_bucket_size;
new_buckets[hc]->appendNode (this->buckets[i]->yield(np)); new_buckets[hc]->appendNode (this->buckets[i]->yield(np));
np = next; np = next;

View File

@ -50,10 +50,8 @@ class QSE_EXPORT HeapMmgr: public Mmgr, public Mmged
{ {
public: public:
/// The constructor function accepts an memory manager \a mmgr that /// The constructor function accepts an memory manager \a mmgr that
/// is used to create a heap of the size \a heap_size. Optionally, /// is used to create a heap of the size \a heap_size.
/// you can ask the memory manager to return #QSE_NULL upon allocation HeapMmgr (Mmgr* mmgr, qse_size_t heap_size);
/// failure by setting \a raise_exception to false.
HeapMmgr (Mmgr* mmgr, qse_size_t heap_size, bool raise_exception = true);
/// The destructor function frees the heap. Memory areas returned by /// The destructor function frees the heap. Memory areas returned by
/// allocate(), reallocate(), allocMem(), reallocMem() are invalidated /// allocate(), reallocate(), allocMem(), reallocMem() are invalidated

View File

@ -103,10 +103,6 @@ public:
this->node_count = 0; this->node_count = 0;
this->head_node = QSE_NULL; this->head_node = QSE_NULL;
this->tail_node = QSE_NULL; this->tail_node = QSE_NULL;
// the memory manager for the linked list must raise an exception
// upon memory allocation error.
QSE_ASSERT (this->getMmgr()->isExceptionRaising());
} }
LinkedList (const SelfType& ll): Mmged(ll.getMmgr()), mp (ll.getMmgr(), ll.mp.getDatumSize(), ll.mp.getBlockSize()) LinkedList (const SelfType& ll): Mmged(ll.getMmgr()), mp (ll.getMmgr(), ll.mp.getDatumSize(), ll.mp.getBlockSize())

View File

@ -52,6 +52,6 @@ pkginclude_HEADERS = \
if ENABLE_CXX if ENABLE_CXX
pkginclude_HEADERS += \ pkginclude_HEADERS += \
Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \
Mpool.hpp Pair.hpp LinkedList.hpp HashList.hpp HashTable.hpp Mpool.hpp Couple.hpp LinkedList.hpp HashList.hpp HashTable.hpp
endif endif

View File

@ -52,7 +52,7 @@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
@ENABLE_CXX_TRUE@am__append_1 = \ @ENABLE_CXX_TRUE@am__append_1 = \
@ENABLE_CXX_TRUE@ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ @ENABLE_CXX_TRUE@ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \
@ENABLE_CXX_TRUE@ Mpool.hpp Pair.hpp LinkedList.hpp HashList.hpp HashTable.hpp @ENABLE_CXX_TRUE@ Mpool.hpp Couple.hpp LinkedList.hpp HashList.hpp HashTable.hpp
subdir = include/qse/cmn subdir = include/qse/cmn
DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \
@ -91,7 +91,7 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dir.h dll.h \
nwio.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sck.h sio.h \ nwio.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sck.h sio.h \
sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \ sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \
utf8.h xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ utf8.h xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \
Mpool.hpp Pair.hpp LinkedList.hpp HashList.hpp HashTable.hpp Mpool.hpp Couple.hpp LinkedList.hpp HashList.hpp HashTable.hpp
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \ am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \

View File

@ -64,7 +64,7 @@ public:
/// The Mmgr() function builds a memory manager composed of bridge /// The Mmgr() function builds a memory manager composed of bridge
/// functions connecting itself with it. /// functions connecting itself with it.
/// ///
Mmgr (bool raise_exception = true): raise_exception (raise_exception) Mmgr ()
{ {
// NOTE: // NOTE:
// the #qse_mmgr_t interface is not affected by raise_exception // the #qse_mmgr_t interface is not affected by raise_exception
@ -81,24 +81,15 @@ public:
/// ///
virtual ~Mmgr () {} virtual ~Mmgr () {}
///
/// The isExceptionRaising() function tells if the memory manager
/// throws an exception upon a memory allocation error.
///
bool isExceptionRaising () const
{
return this->raise_exception;
}
/// ///
/// The allocate() function calls allocMem() for memory /// The allocate() function calls allocMem() for memory
/// allocation. if it fails, it raise an exception if it's /// allocation. if it fails, it raise an exception if it's
/// configured to do so. /// configured to do so.
/// ///
void* allocate (qse_size_t n) void* allocate (qse_size_t n, bool raise_exception = true)
{ {
void* xptr = this->allocMem (n); void* xptr = this->allocMem (n);
if (!xptr && this->raise_exception) QSE_THROW (MemoryError); if (!xptr && raise_exception) QSE_THROW (MemoryError);
return xptr; return xptr;
} }
@ -106,17 +97,17 @@ public:
/// The callocate() function allocates memory like allocate() and /// The callocate() function allocates memory like allocate() and
/// clears the memory before returning. /// clears the memory before returning.
/// ///
void* callocate (qse_size_t n); void* callocate (qse_size_t n, bool raise_exception = true);
/// ///
/// The reallocate() function calls reallocMem() for memory /// The reallocate() function calls reallocMem() for memory
/// reallocation. if it fails, it raise an exception if it's /// reallocation. if it fails, it raise an exception if it's
/// configured to do so. /// configured to do so.
/// ///
void* reallocate (void* ptr, qse_size_t n) void* reallocate (void* ptr, qse_size_t n, bool raise_exception = true)
{ {
void* xptr = this->reallocMem (ptr, n); void* xptr = this->reallocMem (ptr, n);
if (!xptr && this->raise_exception) QSE_THROW (MemoryError); if (!xptr && raise_exception) QSE_THROW (MemoryError);
return xptr; return xptr;
} }

View File

@ -40,7 +40,7 @@ QSE_BEGIN_NAMESPACE(QSE)
class QSE_EXPORT StdMmgr: public Mmgr class QSE_EXPORT StdMmgr: public Mmgr
{ {
public: public:
StdMmgr (bool raise_exception = true): Mmgr (raise_exception) {} StdMmgr (): Mmgr () {}
void* allocMem (qse_size_t n); void* allocMem (qse_size_t n);
void* reallocMem (void* ptr, qse_size_t n); void* reallocMem (void* ptr, qse_size_t n);

View File

@ -36,8 +36,8 @@ struct xma_xtn_t
HeapMmgr* heap; HeapMmgr* heap;
}; };
HeapMmgr::HeapMmgr (Mmgr* mmgr, qse_size_t heap_size, bool raise_exception): HeapMmgr::HeapMmgr (Mmgr* mmgr, qse_size_t heap_size):
Mmgr(raise_exception), Mmged(mmgr), xma(QSE_NULL), heap_size (heap_size) Mmgr(), Mmged(mmgr), xma(QSE_NULL), heap_size (heap_size)
{ {
} }

View File

@ -47,9 +47,9 @@ void Mmgr::free_mem (mmgr_t* mmgr, void* ptr)
((Mmgr*)mmgr->ctx)->freeMem (ptr); ((Mmgr*)mmgr->ctx)->freeMem (ptr);
} }
void* Mmgr::callocate (qse_size_t n) void* Mmgr::callocate (qse_size_t n, bool raise_exception)
{ {
void* ptr = this->allocate (n); void* ptr = this->allocate (n, raise_exception);
QSE_MEMSET (ptr, 0, n); QSE_MEMSET (ptr, 0, n);
return ptr; return ptr;
} }