added Mmgr::callocate()
fixed various problems in HashTable
This commit is contained in:
parent
6e92bb2985
commit
6da46ff4e1
@ -64,44 +64,94 @@ public:
|
||||
typedef LinkedList<Entry> Bucket;
|
||||
typedef HashTable<K,V,HASHER,RESIZER> SelfType;
|
||||
|
||||
protected:
|
||||
Bucket** allocate_bucket (Mmgr* mm, qse_size_t bs) const
|
||||
{
|
||||
Bucket** b = QSE_NULL;
|
||||
|
||||
try
|
||||
{
|
||||
b = (Bucket**) mm->callocate (QSE_SIZEOF(*b) * bs);
|
||||
for (qse_size_t i = 0; i < bs; i++)
|
||||
{
|
||||
b[i] = new(mm) Bucket (mm);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
for (qse_size_t i = bs; i > 0;)
|
||||
{
|
||||
i--;
|
||||
if (b[i])
|
||||
{
|
||||
b[i]->~Bucket ();
|
||||
::operator delete (b, mm);
|
||||
}
|
||||
}
|
||||
mm->dispose (b);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void dispose_bucket (Mmgr* mm, Bucket** b, qse_size_t bs) const
|
||||
{
|
||||
for (qse_size_t i = bs; i > 0;)
|
||||
{
|
||||
i--;
|
||||
if (b[i])
|
||||
{
|
||||
b[i]->~Bucket ();
|
||||
::operator delete (b[i], mm);
|
||||
}
|
||||
}
|
||||
mm->dispose (b);
|
||||
}
|
||||
|
||||
public:
|
||||
HashTable (Mmgr* mmgr, qse_size_t bucket_size = 10, qse_size_t load_factor = 75): Mmged(mmgr)
|
||||
{
|
||||
this->entry_count = 0;
|
||||
this->buckets = this->allocate_bucket (this->getMmgr(), bucket_size);
|
||||
this->bucket_size = bucket_size;
|
||||
this->buckets = new Bucket[bucket_size];
|
||||
this->entry_count = 0;
|
||||
this->load_factor = load_factor;
|
||||
this->threshold = bucket_size * load_factor / 100;
|
||||
}
|
||||
|
||||
HashTable (const SelfType& table)
|
||||
HashTable (const SelfType& table): Mmged (table)
|
||||
{
|
||||
this->entry_count = 0;
|
||||
this->buckets = this->allocate_bucket (this->getMmgr(), table.bucket_size);
|
||||
this->bucket_size = table.bucket_size;
|
||||
this->buckets = new Bucket[table.bucket_size];
|
||||
this->entry_count = 0;
|
||||
this->load_factor = table.load_factor;
|
||||
this->threshold = table.bucket_size * table.load_factor / 100;
|
||||
|
||||
for (qse_size_t i = 0; i < table.bucket_size; i++)
|
||||
{
|
||||
Bucket& b = table.buckets[i];
|
||||
Bucket* b = table.buckets[i];
|
||||
typename Bucket::Node* np;
|
||||
for (np = b.head(); np; np = np->forward())
|
||||
for (np = b->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
qse_size_t hc = this->hasher(e.key) % this->bucket_size;
|
||||
this->buckets[hc].append (e);
|
||||
this->buckets[hc]->append (e);
|
||||
this->entry_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// doesn't need to rehash in the copy constructor.
|
||||
//if (entry_count >= threshold) rehash ();
|
||||
//if (entry_count >= threshold) this->rehash ();
|
||||
}
|
||||
|
||||
~HashTable ()
|
||||
{
|
||||
this->clear ();
|
||||
if (this->buckets) delete[] this->buckets;
|
||||
this->dispose_bucket (this->getMmgr(), this->buckets, this->bucket_size);
|
||||
}
|
||||
|
||||
SelfType& operator= (const SelfType& table)
|
||||
@ -110,13 +160,13 @@ public:
|
||||
|
||||
for (qse_size_t i = 0; i < table.bucket_size; i++)
|
||||
{
|
||||
Bucket& b = table.buckets[i];
|
||||
Bucket* b = table.buckets[i];
|
||||
typename Bucket::Node* np;
|
||||
for (np = b.head(); np; np = np->forward())
|
||||
for (np = b->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
qse_size_t hc = this->hasher(e.key) % this->bucket_size;
|
||||
this->buckets[hc].append (e);
|
||||
this->buckets[hc]->append (e);
|
||||
entry_count++;
|
||||
}
|
||||
}
|
||||
@ -142,7 +192,7 @@ public:
|
||||
|
||||
Bucket& getBucket (qse_size_t index) const
|
||||
{
|
||||
qse_assert (index < this->bucket_size);
|
||||
QSE_ASSERT (index < this->bucket_size);
|
||||
return this->buckets[index];
|
||||
}
|
||||
|
||||
@ -152,7 +202,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % this->bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return e.value;
|
||||
@ -164,7 +214,7 @@ public:
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e2 = buckets[hc].append (Entry(key));
|
||||
Entry& e2 = this->buckets[hc]->append (Entry(key));
|
||||
entry_count++;
|
||||
return e2.value;
|
||||
}
|
||||
@ -174,7 +224,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % this->bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return e.value;
|
||||
@ -186,7 +236,7 @@ public:
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e2 = buckets[hc].append (Entry(key));
|
||||
Entry& e2 = this->buckets[hc]->append (Entry(key));
|
||||
entry_count++;
|
||||
return e2.value;
|
||||
}
|
||||
@ -204,7 +254,8 @@ public:
|
||||
qse_size_t hc = h(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward()) {
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
const Entry& e = np->value;
|
||||
if (key == e.key) return &e.value;
|
||||
}
|
||||
@ -219,7 +270,8 @@ public:
|
||||
qse_size_t hc = h(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward()) {
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return &e.value;
|
||||
}
|
||||
@ -227,40 +279,56 @@ public:
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
V* get (const K& key)
|
||||
protected:
|
||||
Entry* find_pair (const K& key)
|
||||
{
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward()) {
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return &e.value;
|
||||
if (key == e.key) return &e;
|
||||
}
|
||||
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const V* get (const K& key) const
|
||||
public:
|
||||
Entry* findPair (const K& key)
|
||||
{
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward()) {
|
||||
const Entry& e = np->value;
|
||||
if (key == e.key) return &e.value;
|
||||
return this->find_pair (key);
|
||||
}
|
||||
|
||||
const Entry* findPair (const K& key) const
|
||||
{
|
||||
return this->find_pair (key);
|
||||
}
|
||||
|
||||
V* findValue (const K& key)
|
||||
{
|
||||
Entry* pair = this->findPair (key);
|
||||
if (pair) return &pair->value;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
V* get (const K& key, qse_size_t* hash_code, typename Bucket::Node** node)
|
||||
const V* findValue (const K& key) const
|
||||
{
|
||||
const Entry* pair = this->findPair (key);
|
||||
if (pair) return &pair->value;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
V* findValue (const K& key, qse_size_t* hash_code, typename Bucket::Node** node)
|
||||
{
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward()) {
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) {
|
||||
if (key == e.key)
|
||||
{
|
||||
*hash_code = hc;
|
||||
*node = np;
|
||||
return &e.value;
|
||||
@ -270,12 +338,12 @@ public:
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
const V* get (const K& key, qse_size_t* hash_code, typename Bucket::Node** node) const
|
||||
const V* findValue (const K& key, qse_size_t* hash_code, typename Bucket::Node** node) const
|
||||
{
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key)
|
||||
@ -305,7 +373,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return &e.value;
|
||||
@ -313,11 +381,11 @@ public:
|
||||
|
||||
if (entry_count >= threshold)
|
||||
{
|
||||
rehash ();
|
||||
this->rehash ();
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e = buckets[hc].append (Entry(key));
|
||||
Entry& e = this->buckets[hc]->append (Entry(key));
|
||||
entry_count++;
|
||||
return &e.value;
|
||||
}
|
||||
@ -327,7 +395,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return &e.value;
|
||||
@ -335,11 +403,11 @@ public:
|
||||
|
||||
if (entry_count >= threshold)
|
||||
{
|
||||
rehash ();
|
||||
this->rehash ();
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e = buckets[hc].append (Entry(key,value));
|
||||
Entry& e = this->buckets[hc]->append (Entry(key,value));
|
||||
entry_count++;
|
||||
return &e.value;
|
||||
}
|
||||
@ -349,7 +417,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return QSE_NULL;
|
||||
@ -357,11 +425,11 @@ public:
|
||||
|
||||
if (entry_count >= threshold)
|
||||
{
|
||||
rehash ();
|
||||
this->rehash ();
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e = buckets[hc].append (Entry(key));
|
||||
Entry& e = this->buckets[hc]->append (Entry(key));
|
||||
entry_count++;
|
||||
return &e.value;
|
||||
}
|
||||
@ -371,7 +439,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return QSE_NULL;
|
||||
@ -379,11 +447,11 @@ public:
|
||||
|
||||
if (entry_count >= threshold)
|
||||
{
|
||||
rehash ();
|
||||
this->rehash ();
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e = buckets[hc].append (Entry(key, value));
|
||||
Entry& e = this->buckets[hc]->append (Entry(key, value));
|
||||
entry_count++;
|
||||
return &e.value;
|
||||
}
|
||||
@ -393,7 +461,7 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key)
|
||||
@ -405,11 +473,11 @@ public:
|
||||
|
||||
if (entry_count >= threshold)
|
||||
{
|
||||
rehash ();
|
||||
this->rehash ();
|
||||
hc = this->hasher(key) % bucket_size;
|
||||
}
|
||||
|
||||
Entry& e = buckets[hc].append (Entry(key,value));
|
||||
Entry& e = this->buckets[hc]->append (Entry(key,value));
|
||||
entry_count++;
|
||||
return &e.value;
|
||||
}
|
||||
@ -421,12 +489,12 @@ public:
|
||||
qse_size_t hc = h(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key)
|
||||
{
|
||||
this->buckets[hc].remove (np);
|
||||
this->buckets[hc]->remove (np);
|
||||
this->entry_count--;
|
||||
return 0;
|
||||
}
|
||||
@ -440,12 +508,12 @@ public:
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key)
|
||||
{
|
||||
this->buckets[hc].remove (np);
|
||||
this->buckets[hc]->remove (np);
|
||||
this->entry_count--;
|
||||
return 0;
|
||||
}
|
||||
@ -459,11 +527,12 @@ public:
|
||||
//
|
||||
// WARNING: this method should be used with extra care.
|
||||
//
|
||||
this->buckets[hc].remove (np);
|
||||
this->buckets[hc]->remove (np);
|
||||
this->entry_count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
qse_size_t removeValue (const V& value)
|
||||
{
|
||||
qse_size_t count = 0;
|
||||
@ -471,11 +540,13 @@ public:
|
||||
for (qse_size_t i = 0; i < this->bucket_size; i++)
|
||||
{
|
||||
typename Bucket::Node* np, * np2;
|
||||
np = buckets[i].head();
|
||||
while (np != QSE_NULL) {
|
||||
np = this->buckets[i]->getHeadNode();
|
||||
while (np != QSE_NULL)
|
||||
{
|
||||
Entry& e = np->value;
|
||||
np2 = np->forward ();
|
||||
if (value == e.value) {
|
||||
np2 = np->getNext ();
|
||||
if (value == e.value)
|
||||
{
|
||||
this->remove (i, np);
|
||||
count++;
|
||||
}
|
||||
@ -485,13 +556,14 @@ public:
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool containsKey (const K& key) const
|
||||
{
|
||||
qse_size_t hc = this->hasher(key) % bucket_size;
|
||||
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[hc].head(); np; np = np->forward())
|
||||
for (np = this->buckets[hc]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (key == e.key) return true;
|
||||
@ -505,7 +577,7 @@ public:
|
||||
for (qse_size_t i = 0; i < bucket_size; i++)
|
||||
{
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[i].head(); np; np = np->forward())
|
||||
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (value == e.value) return true;
|
||||
@ -515,18 +587,19 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void clear (int new_bucket_size = 0)
|
||||
void clear (qse_size_t new_bucket_size = 0)
|
||||
{
|
||||
for (qse_size_t i = 0; i < bucket_size; i++) buckets[i].clear ();
|
||||
entry_count = 0;
|
||||
for (qse_size_t i = 0; i < bucket_size; i++) this->buckets[i]->clear ();
|
||||
this->entry_count = 0;
|
||||
|
||||
if (new_bucket_size > 0)
|
||||
{
|
||||
Bucket* tmp = new Bucket[new_bucket_size];
|
||||
bucket_size = new_bucket_size;
|
||||
threshold = bucket_size * load_factor / 100;
|
||||
delete[] buckets;
|
||||
buckets = tmp;
|
||||
Bucket** tmp = this->allocate_bucket (this->getMmgr(), new_bucket_size);
|
||||
this->dispose_bucket (this->getMmgr(), this->buckets, this->bucket_size);
|
||||
|
||||
this->buckets = tmp;
|
||||
this->bucket_size = new_bucket_size;
|
||||
this->threshold = this->bucket_size * this->load_factor / 100;
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,7 +611,7 @@ public:
|
||||
for (qse_size_t i = 0; i < this->bucket_size; i++)
|
||||
{
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[i].head(); np; np = np->forward())
|
||||
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
const Entry& e = np->value;
|
||||
if ((this->*callback)(e,user_data) == -1) return -1;
|
||||
@ -556,7 +629,7 @@ public:
|
||||
for (qse_size_t i = 0; i < this->bucket_size; i++)
|
||||
{
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[i].head(); np; np = np->forward())
|
||||
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
Entry& e = np->value;
|
||||
if (callback(this,e,user_data) == -1) return -1;
|
||||
@ -569,7 +642,7 @@ public:
|
||||
protected:
|
||||
mutable qse_size_t entry_count;
|
||||
mutable qse_size_t bucket_size;
|
||||
mutable Bucket* buckets;
|
||||
mutable Bucket** buckets;
|
||||
mutable qse_size_t threshold;
|
||||
qse_size_t load_factor;
|
||||
HASHER hasher;
|
||||
@ -578,7 +651,7 @@ protected:
|
||||
void rehash () const
|
||||
{
|
||||
qse_size_t new_bucket_size = this->resizer (this->bucket_size);
|
||||
Bucket* new_buckets = new Bucket[new_bucket_size];
|
||||
Bucket** new_buckets = this->allocate_bucket (this->getMmgr(), new_bucket_size);
|
||||
|
||||
try
|
||||
{
|
||||
@ -586,11 +659,11 @@ protected:
|
||||
{
|
||||
/*
|
||||
typename Bucket::Node* np;
|
||||
for (np = buckets[i].head(); np; np = np->forward())
|
||||
for (np = this->buckets[i]->getHeadNode(); np; np = np->getNext())
|
||||
{
|
||||
const Entry& e = np->value;
|
||||
qse_size_t hc = e.key.hashCode() % new_bucket_size;
|
||||
new_buckets[hc].append (e);
|
||||
new_this->buckets[hc]->append (e);
|
||||
}
|
||||
*/
|
||||
|
||||
@ -599,24 +672,25 @@ protected:
|
||||
// if the bucket uses a memory pool, this would not
|
||||
// work. fortunately, the hash table doesn't use it
|
||||
// for a bucket.
|
||||
typename Bucket::Node* np = buckets[i].head();
|
||||
typename Bucket::Node* np = this->buckets[i]->getHeadNode();
|
||||
while (np)
|
||||
{
|
||||
typename Bucket::Node* next = np->forward();
|
||||
typename Bucket::Node* next = np->getNext();
|
||||
const Entry& e = np->value;
|
||||
qse_size_t hc = this->hasher(e.key) % new_bucket_size;
|
||||
new_buckets[hc].appendNode (buckets[i].yield(np));
|
||||
new_buckets[hc]->appendNode (this->buckets[i]->yield(np));
|
||||
np = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete[] new_buckets;
|
||||
this->dispose_bucket (this->getMmgr(), new_buckets, new_bucket_size);
|
||||
throw;
|
||||
}
|
||||
|
||||
delete[] this->buckets;
|
||||
this->dispose_bucket (this->getMmgr(), this->buckets, this->bucket_size);
|
||||
|
||||
this->buckets = new_buckets;
|
||||
this->bucket_size = new_bucket_size;
|
||||
this->threshold = this->load_factor * this->bucket_size / 100;
|
||||
|
@ -127,6 +127,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if 0
|
||||
T& operator[] (qse_size_t index)
|
||||
{
|
||||
// same as getValueAt()
|
||||
@ -142,6 +143,7 @@ public:
|
||||
Node* np = this->getNodeAt (index);
|
||||
return np->value;
|
||||
}
|
||||
#endif
|
||||
|
||||
qse_size_t getMPBlockSize() const
|
||||
{
|
||||
|
@ -102,6 +102,12 @@ public:
|
||||
return xptr;
|
||||
}
|
||||
|
||||
///
|
||||
/// The callocate() function allocates memory like allocate() and
|
||||
/// clears the memory before returning.
|
||||
///
|
||||
void* callocate (qse_size_t n);
|
||||
|
||||
///
|
||||
/// The reallocate() function calls reallocMem() for memory
|
||||
/// reallocation. if it fails, it raise an exception if it's
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <qse/cmn/Mmgr.hpp>
|
||||
#include <qse/cmn/StdMmgr.hpp>
|
||||
#include "mem.h"
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
@ -46,6 +47,13 @@ void Mmgr::free_mem (mmgr_t* mmgr, void* ptr)
|
||||
((Mmgr*)mmgr->ctx)->freeMem (ptr);
|
||||
}
|
||||
|
||||
void* Mmgr::callocate (qse_size_t n)
|
||||
{
|
||||
void* ptr = this->allocate (n);
|
||||
QSE_MEMSET (ptr, 0, n);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Mmgr* Mmgr::dfl_mmgr = StdMmgr::getInstance();
|
||||
|
||||
Mmgr* Mmgr::getDFL ()
|
||||
|
Loading…
Reference in New Issue
Block a user