From 6e92bb29854684e477f63934867b3b2700e72657 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 4 Feb 2015 13:43:01 +0000 Subject: [PATCH] added Pair and HashTable --- qse/include/qse/cmn/HashList.hpp | 21 +- qse/include/qse/cmn/HashTable.hpp | 630 ++++++++++++++++++ qse/include/qse/cmn/HeapMmgr.hpp | 20 +- qse/include/qse/cmn/LinkedList.hpp | 4 + qse/include/qse/cmn/Makefile.am | 2 +- qse/include/qse/cmn/Makefile.in | 4 +- qse/include/qse/cmn/Mmgr.hpp | 9 + .../qse/cmn/{Mpoolable.hpp => Pair.hpp} | 50 +- qse/lib/cmn/HeapMmgr.cpp | 5 +- 9 files changed, 700 insertions(+), 45 deletions(-) create mode 100644 qse/include/qse/cmn/HashTable.hpp rename qse/include/qse/cmn/{Mpoolable.hpp => Pair.hpp} (66%) diff --git a/qse/include/qse/cmn/HashList.hpp b/qse/include/qse/cmn/HashList.hpp index e71f0c34..7b75e216 100644 --- a/qse/include/qse/cmn/HashList.hpp +++ b/qse/include/qse/cmn/HashList.hpp @@ -52,7 +52,19 @@ struct HashListComparator } }; -template , typename COMPARATOR = HashListComparator > +struct HashListResizer +{ + qse_size_t operator() (qse_size_t current) const + { + return (current < 5000)? (current + current): + (current < 50000)? (current + (current / 2)): + (current < 100000)? (current + (current / 4)): + (current < 150000)? (current + (current / 8)): + (current + (current / 16)); + } +}; + +template , typename COMPARATOR = HashListComparator, typename RESIZER = HashListResizer > class HashList: public Mmged { public: @@ -114,6 +126,10 @@ public: this->load_factor = load_factor; 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) @@ -428,13 +444,14 @@ protected: qse_size_t load_factor; HASHER hasher; COMPARATOR comparator; + RESIZER resizer; void rehash () { // Move nodes around instead of values to prevent // existing values from being copied over and destroyed. // this incurs less number of memory allocations also. - SelfType temp (this->getMmgr(), this->node_capacity << 1, this->load_factor, this->datum_list->getMPBlockSize()); + SelfType temp (this->getMmgr(), this->resizer(this->node_capacity), this->load_factor, this->datum_list->getMPBlockSize()); Node* p = this->datum_list->getHeadNode(); while (p) { diff --git a/qse/include/qse/cmn/HashTable.hpp b/qse/include/qse/cmn/HashTable.hpp new file mode 100644 index 00000000..7f70c492 --- /dev/null +++ b/qse/include/qse/cmn/HashTable.hpp @@ -0,0 +1,630 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _QSE_CMN_HASHTABLE_HPP_ +#define _QSE_CMN_HASHTABLE_HPP_ + +#include +#include +#include + +///////////////////////////////// +QSE_BEGIN_NAMESPACE(QSE) +///////////////////////////////// + +template +struct HashTableHasher +{ + qse_size_t operator() (const T& v) const + { + return v.hashCode(); + } +}; + +struct HashTableResizer +{ + qse_size_t operator() (qse_size_t current) const + { + return (current < 5000)? (current + current): + (current < 50000)? (current + (current / 2)): + (current < 100000)? (current + (current / 4)): + (current < 150000)? (current + (current / 8)): + (current + (current / 16)); + } +}; + +template , typename RESIZER = HashTableResizer> +class HashTable: public Mmged +{ +public: + typedef Pair Entry; + typedef LinkedList Bucket; + typedef HashTable SelfType; + + HashTable (Mmgr* mmgr, qse_size_t bucket_size = 10, qse_size_t load_factor = 75): Mmged(mmgr) + { + this->entry_count = 0; + this->bucket_size = bucket_size; + this->buckets = new Bucket[bucket_size]; + this->load_factor = load_factor; + this->threshold = bucket_size * load_factor / 100; + } + + HashTable (const SelfType& table) + { + this->entry_count = 0; + this->bucket_size = table.bucket_size; + this->buckets = new Bucket[table.bucket_size]; + 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]; + typename Bucket::Node* np; + for (np = b.head(); np; np = np->forward()) + { + Entry& e = np->value; + qse_size_t hc = this->hasher(e.key) % this->bucket_size; + this->buckets[hc].append (e); + this->entry_count++; + } + } + + // doesn't need to rehash in the copy constructor. + //if (entry_count >= threshold) rehash (); + } + + ~HashTable () + { + this->clear (); + if (this->buckets) delete[] this->buckets; + } + + SelfType& operator= (const SelfType& table) + { + this->clear (); + + for (qse_size_t i = 0; i < table.bucket_size; i++) + { + Bucket& b = table.buckets[i]; + typename Bucket::Node* np; + for (np = b.head(); np; np = np->forward()) + { + Entry& e = np->value; + qse_size_t hc = this->hasher(e.key) % this->bucket_size; + this->buckets[hc].append (e); + entry_count++; + } + } + + if (this->entry_count >= this->threshold) this->rehash (); + return *this; + } + + qse_size_t getSize () const + { + return this->entry_count; + } + + bool isEmpty () const + { + return this->entry_count == 0; + } + + qse_size_t getBucketSize () const + { + return this->bucket_size; + } + + Bucket& getBucket (qse_size_t index) const + { + qse_assert (index < this->bucket_size); + return this->buckets[index]; + } + +#if 0 + V& operator[] (const K& key) + { + qse_size_t hc = this->hasher(key) % this->bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (key == e.key) return e.value; + } + + if (entry_count >= threshold) + { + this->rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e2 = buckets[hc].append (Entry(key)); + entry_count++; + return e2.value; + } + + const V& operator[] (const K& key) const + { + qse_size_t hc = this->hasher(key) % this->bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (key == e.key) return e.value; + } + + if (entry_count >= threshold) + { + this->rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e2 = buckets[hc].append (Entry(key)); + entry_count++; + return e2.value; + } +#endif + + // + // NOTE: getConstWithCustomKey() and getWithCustomKey() would + // not need to have different names if compilers were smarter. + // + + template + const V* getConstWithCustomKey (const MK& key) const + { + MHASHER h; + qse_size_t hc = h(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 QSE_NULL; + } + + template + V* getWithCustomKey (const MK& key) const + { + MHASHER h; + qse_size_t hc = h(key) % bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) { + Entry& e = np->value; + if (key == e.key) return &e.value; + } + + return QSE_NULL; + } + + V* get (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()) { + Entry& e = np->value; + if (key == e.key) return &e.value; + } + + return QSE_NULL; + } + + const V* get (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()) { + const Entry& e = np->value; + if (key == e.key) return &e.value; + } + + return QSE_NULL; + } + + V* get (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()) { + Entry& e = np->value; + if (key == e.key) { + *hash_code = hc; + *node = np; + return &e.value; + } + } + + return QSE_NULL; + } + + const V* get (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()) + { + Entry& e = np->value; + if (key == e.key) + { + *hash_code = hc; + *node = np; + return &e.value; + } + } + + return QSE_NULL; + } + + int put (const K& key, const V& value) + { + upsert (key, value); + return 0; + } + + int putNew (const K& key, const V& value) + { + return (insertNew(key,value) == QSE_NULL)? -1: 0; + } + + V* insert (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()) + { + Entry& e = np->value; + if (key == e.key) return &e.value; + } + + if (entry_count >= threshold) + { + rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e = buckets[hc].append (Entry(key)); + entry_count++; + return &e.value; + } + + V* insert (const K& key, const V& value) + { + qse_size_t hc = this->hasher(key) % bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (key == e.key) return &e.value; + } + + if (entry_count >= threshold) + { + rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e = buckets[hc].append (Entry(key,value)); + entry_count++; + return &e.value; + } + + V* insertNew (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()) + { + Entry& e = np->value; + if (key == e.key) return QSE_NULL; + } + + if (entry_count >= threshold) + { + rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e = buckets[hc].append (Entry(key)); + entry_count++; + return &e.value; + } + + V* insertNew (const K& key, const V& value) + { + qse_size_t hc = this->hasher(key) % bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (key == e.key) return QSE_NULL; + } + + if (entry_count >= threshold) + { + rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e = buckets[hc].append (Entry(key, value)); + entry_count++; + return &e.value; + } + + V* upsert (const K& key, const V& value) + { + qse_size_t hc = this->hasher(key) % bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (key == e.key) + { + e.value = value; + return &e.value; + } + } + + if (entry_count >= threshold) + { + rehash (); + hc = this->hasher(key) % bucket_size; + } + + Entry& e = buckets[hc].append (Entry(key,value)); + entry_count++; + return &e.value; + } + + template + int removeWithCustomKey (const MK& key) + { + MHASHER h; + qse_size_t hc = h(key) % bucket_size; + + typename Bucket::Node* np; + for (np = buckets[hc].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (key == e.key) + { + this->buckets[hc].remove (np); + this->entry_count--; + return 0; + } + } + + return -1; + } + + int remove (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()) + { + Entry& e = np->value; + if (key == e.key) + { + this->buckets[hc].remove (np); + this->entry_count--; + return 0; + } + } + + return -1; + } + + int remove (qse_size_t hc, typename Bucket::Node* np) + { + // + // WARNING: this method should be used with extra care. + // + this->buckets[hc].remove (np); + this->entry_count--; + return 0; + } + + qse_size_t removeValue (const V& value) + { + qse_size_t count = 0; + + for (qse_size_t i = 0; i < this->bucket_size; i++) + { + typename Bucket::Node* np, * np2; + np = buckets[i].head(); + while (np != QSE_NULL) { + Entry& e = np->value; + np2 = np->forward (); + if (value == e.value) { + this->remove (i, np); + count++; + } + np = np2; + } + } + + return count; + } + + 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()) + { + Entry& e = np->value; + if (key == e.key) return true; + } + + return false; + } + + bool containsValue (const K& value) const + { + for (qse_size_t i = 0; i < bucket_size; i++) + { + typename Bucket::Node* np; + for (np = buckets[i].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (value == e.value) return true; + } + } + + return false; + } + + void clear (int new_bucket_size = 0) + { + for (qse_size_t i = 0; i < bucket_size; i++) buckets[i].clear (); + 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; + } + } + + typedef int (SelfType::*TraverseCallback) + (const Entry& entry, void* user_data) const; + + int traverse (TraverseCallback callback, void* user_data) const + { + for (qse_size_t i = 0; i < this->bucket_size; i++) + { + typename Bucket::Node* np; + for (np = buckets[i].head(); np; np = np->forward()) + { + const Entry& e = np->value; + if ((this->*callback)(e,user_data) == -1) return -1; + } + } + + return 0; + } + + typedef int (*StaticTraverseCallback) + (SelfType* table, Entry& entry, void* user_data); + + int traverse (StaticTraverseCallback callback, void* user_data) + { + for (qse_size_t i = 0; i < this->bucket_size; i++) + { + typename Bucket::Node* np; + for (np = buckets[i].head(); np; np = np->forward()) + { + Entry& e = np->value; + if (callback(this,e,user_data) == -1) return -1; + } + } + + return 0; + } + +protected: + mutable qse_size_t entry_count; + mutable qse_size_t bucket_size; + mutable Bucket* buckets; + mutable qse_size_t threshold; + qse_size_t load_factor; + HASHER hasher; + RESIZER resizer; + + void rehash () const + { + qse_size_t new_bucket_size = this->resizer (this->bucket_size); + Bucket* new_buckets = new Bucket[new_bucket_size]; + + try + { + for (qse_size_t i = 0; i < this->bucket_size; i++) + { + /* + typename Bucket::Node* np; + for (np = buckets[i].head(); np; np = np->forward()) + { + const Entry& e = np->value; + qse_size_t hc = e.key.hashCode() % new_bucket_size; + new_buckets[hc].append (e); + } + */ + + // this approach save redundant memory allocation + // and retains the previous pointers before rehashing. + // 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(); + while (np) + { + typename Bucket::Node* next = np->forward(); + const Entry& e = np->value; + qse_size_t hc = this->hasher(e.key) % new_bucket_size; + new_buckets[hc].appendNode (buckets[i].yield(np)); + np = next; + } + } + } + catch (...) + { + delete[] new_buckets; + throw; + } + + delete[] this->buckets; + this->buckets = new_buckets; + this->bucket_size = new_bucket_size; + this->threshold = this->load_factor * this->bucket_size / 100; + } +}; + +///////////////////////////////// +QSE_END_NAMESPACE(QSE) +///////////////////////////////// + +#endif diff --git a/qse/include/qse/cmn/HeapMmgr.hpp b/qse/include/qse/cmn/HeapMmgr.hpp index f6724b64..7d66609f 100644 --- a/qse/include/qse/cmn/HeapMmgr.hpp +++ b/qse/include/qse/cmn/HeapMmgr.hpp @@ -35,13 +35,29 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -/// The HeapMmgr class implements the heap-based memory manager interface. -/// It is a memory manager that's memory managed by another memory manager. +/// The HeapMmgr class implements a memory management interface that +/// handles a memory heap of a given size. Notably, it is a memory manager +/// managed by another memory manager. +/// +/// \code +/// QSE::HeapMmgr heap_mmgr (QSE::Mmgr::getDFL(), 30000); +/// QSE::LinkedList int_list (&heap_mmgr); +/// int_list.append (10); +/// int_list.append (20); +/// \endcode class QSE_EXPORT HeapMmgr: public Mmgr, public Mmged { public: + /// The constructor function accepts an memory manager \a mmgr that + /// is used to create a heap of the size \a heap_size. Optionally, + /// you can ask the memory manager to return #QSE_NULL upon allocation + /// 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 + /// allocate(), reallocate(), allocMem(), reallocMem() are invalidated + /// all at once. ~HeapMmgr (); void* allocMem (qse_size_t n); diff --git a/qse/include/qse/cmn/LinkedList.hpp b/qse/include/qse/cmn/LinkedList.hpp index b4360443..1ceaaa2e 100644 --- a/qse/include/qse/cmn/LinkedList.hpp +++ b/qse/include/qse/cmn/LinkedList.hpp @@ -103,6 +103,10 @@ public: this->node_count = 0; this->head_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()) diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am index 7741aee6..75d13be9 100644 --- a/qse/include/qse/cmn/Makefile.am +++ b/qse/include/qse/cmn/Makefile.am @@ -52,6 +52,6 @@ pkginclude_HEADERS = \ if ENABLE_CXX pkginclude_HEADERS += \ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ - Mpool.hpp Mpoolable.hpp LinkedList.hpp HashList.hpp + Mpool.hpp Pair.hpp LinkedList.hpp HashList.hpp HashTable.hpp endif diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in index 86dce87c..df901e3a 100644 --- a/qse/include/qse/cmn/Makefile.in +++ b/qse/include/qse/cmn/Makefile.in @@ -52,7 +52,7 @@ build_triplet = @build@ host_triplet = @host@ @ENABLE_CXX_TRUE@am__append_1 = \ @ENABLE_CXX_TRUE@ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ -@ENABLE_CXX_TRUE@ Mpool.hpp Mpoolable.hpp LinkedList.hpp HashList.hpp +@ENABLE_CXX_TRUE@ Mpool.hpp Pair.hpp LinkedList.hpp HashList.hpp HashTable.hpp subdir = include/qse/cmn 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 \ 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 \ - Mpool.hpp Mpoolable.hpp LinkedList.hpp HashList.hpp + Mpool.hpp Pair.hpp LinkedList.hpp HashList.hpp HashTable.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ diff --git a/qse/include/qse/cmn/Mmgr.hpp b/qse/include/qse/cmn/Mmgr.hpp index 5de90293..fa58ace2 100644 --- a/qse/include/qse/cmn/Mmgr.hpp +++ b/qse/include/qse/cmn/Mmgr.hpp @@ -81,6 +81,15 @@ public: /// 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 /// allocation. if it fails, it raise an exception if it's diff --git a/qse/include/qse/cmn/Mpoolable.hpp b/qse/include/qse/cmn/Pair.hpp similarity index 66% rename from qse/include/qse/cmn/Mpoolable.hpp rename to qse/include/qse/cmn/Pair.hpp index a221859b..8b24b38c 100644 --- a/qse/include/qse/cmn/Mpoolable.hpp +++ b/qse/include/qse/cmn/Pair.hpp @@ -24,52 +24,34 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _QSE_CMN_MPOOLABLE_HPP_ -#define _QSE_CMN_MPOOLABLE_HPP_ +#ifndef _QSE_CMN_PAIR_HPP_ +#define _QSE_CMN_PAIR_HPP_ -#include - -// use size_t as some compilers complain about qse_size_t used in new(). -#include +#include +#include ///////////////////////////////// QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -class QSE_EXPORT Mpoolable +template class Pair { public: + KEY key; + VALUE value; -/* - inline void* operator new (mp_size_t size) - { - return ::operator new (size); - } + Pair () {} + Pair (const KEY& key): key (key) {} + Pair (const KEY& key, const VALUE& value): key (key), value (value) {} - inline void operator delete (void* ptr) - { - ::operator delete (ptr); - } -*/ + KEY& getKey () { return this->key; } + const KEY& getKey () const { return this->key; } - inline void* operator new (size_t size, Mpool* mp) - { - return mp->isEnabled()? mp->allocate (): ::operator new (size); - } + VALUE& getValue () { return this->value; } + const VALUE& getValue () const { return this->value; } -#if defined(_MSC_VER) - void operator delete (void* ptr, Mpool* mp) - { - if (mp->isEnabled()) mp->dispose (ptr); - else ::operator delete (mp); - } -#else - inline void dispose (void* ptr, Mpool* mp) - { - if (mp->isEnabled()) mp->dispose (ptr); - else ::operator delete (mp); - } -#endif + void setKey (const KEY& key) { this->key = key; } + void setValue (const VALUE& value) { this->value = value; } }; ///////////////////////////////// diff --git a/qse/lib/cmn/HeapMmgr.cpp b/qse/lib/cmn/HeapMmgr.cpp index c4126424..d7df6efb 100644 --- a/qse/lib/cmn/HeapMmgr.cpp +++ b/qse/lib/cmn/HeapMmgr.cpp @@ -80,10 +80,7 @@ void* HeapMmgr::reallocMem (void* ptr, qse_size_t n) void HeapMmgr::freeMem (void* ptr) { - if (this->xma) - { - qse_xma_free (this->xma, ptr); - } + if (this->xma) qse_xma_free (this->xma, ptr); } /////////////////////////////////