added Mpool::swap().

fixed a bug in HashList::rehash() when the memory pool is enabled.
added LinkedList::reverse()
This commit is contained in:
hyung-hwan 2015-02-24 15:42:45 +00:00
parent 890097af66
commit 37792be000
4 changed files with 135 additions and 90 deletions

View File

@ -199,6 +199,11 @@ public:
if (this->datum_list) this->free_datum_list (); if (this->datum_list) this->free_datum_list ();
} }
Mpool& getMpool ()
{
return this->datum_list->getMpool ();
}
SelfType& operator= (const SelfType& list) SelfType& operator= (const SelfType& list)
{ {
this->clear (); this->clear ();
@ -301,12 +306,12 @@ protected:
if (nodes[head] == QSE_NULL) if (nodes[head] == QSE_NULL)
{ {
this->nodes[head] = this->datum_list->insertValue (QSE_NULL, datum); this->nodes[head] = this->datum_list->insert ((Node*)QSE_NULL, datum);
this->nodes[tail] = this->nodes[head]; this->nodes[tail] = this->nodes[head];
} }
else else
{ {
this->nodes[head] = datum_list->insertValue (this->nodes[head], datum); this->nodes[head] = datum_list->insert (this->nodes[head], datum);
} }
return this->nodes[head]; return this->nodes[head];
@ -467,7 +472,13 @@ protected:
// Move nodes around instead of values to prevent // Move nodes around instead of values to prevent
// existing values from being copied over and destroyed. // existing values from being copied over and destroyed.
// this incurs less number of memory allocations also. // this incurs less number of memory allocations also.
SelfType temp (this->getMmgr(), this->resizer(this->node_capacity), this->load_factor, this->datum_list->getMPBlockSize()); Mpool& mpool = this->getMpool();
// Using the memory pool block size of 0 is OK because the nodes
// to be inserted are yielded off the original list and inserted
// without new allocation.
//SelfType temp (this->getMmgr(), this->resizer(this->node_capacity), this->load_factor, mpool.getBlockSize());
SelfType temp (this->getMmgr(), this->resizer(this->node_capacity), this->load_factor, 0);
Node* p = this->datum_list->getHeadNode(); Node* p = this->datum_list->getHeadNode();
while (p) while (p)
{ {
@ -491,7 +502,7 @@ protected:
} }
else else
{ {
temp.nodes[head] = temp.datum_list->insertNode (QSE_NULL, pp); temp.nodes[head] = temp.datum_list->insertNode ((Node*)QSE_NULL, pp);
temp.nodes[tail] = temp.nodes[head]; temp.nodes[tail] = temp.nodes[head];
} }
@ -507,7 +518,13 @@ protected:
this->nodes[i] = QSE_NULL; this->nodes[i] = QSE_NULL;
} }
// swap the contents // swapping the memory pool is a critical thing to do
// especially when the memory pooling is enabled. the datum node in
// 'temp' is actual allocated inside 'mpool' not inside temp.getMpool().
// it is because yield() has been used for insertion into 'temp'.
mpool.swap (temp.getMpool());
// swap the actual contents
qse_size_t temp_capa = temp.node_capacity; qse_size_t temp_capa = temp.node_capacity;
Node** temp_nodes = temp.nodes; Node** temp_nodes = temp.nodes;
DatumList* temp_datum_list = temp.datum_list; DatumList* temp_datum_list = temp.datum_list;
@ -539,12 +556,12 @@ protected:
if (new_nodes[head] == QSE_NULL) if (new_nodes[head] == QSE_NULL)
{ {
new_nodes[head] = new_datum_list->insertValue (QSE_NULL, t); new_nodes[head] = new_datum_list->insert ((Node*)QSE_NULL, t);
new_nodes[tail] = new_nodes[head]; new_nodes[tail] = new_nodes[head];
} }
else else
{ {
new_nodes[head] = new_datum_list->insertValue (new_nodes[head], t); new_nodes[head] = new_datum_list->insert (new_nodes[head], t);
} }
} }

View File

@ -46,8 +46,8 @@ public:
T value; // you can use this variable or accessor functions below T value; // you can use this variable or accessor functions below
protected: protected:
SelfType* next;
SelfType* prev; SelfType* prev;
SelfType* next;
public: public:
T& getValue () { return this->value; } T& getValue () { return this->value; }
@ -126,13 +126,13 @@ public:
return saved; return saved;
} }
int operator== (const SelfType& it) const bool operator== (const SelfType& it) const
{ {
QSE_ASSERT (this->current != QSE_NULL); QSE_ASSERT (this->current != QSE_NULL);
return this->current == it.current; return this->current == it.current;
} }
int operator!= (const SelfType& it) const bool operator!= (const SelfType& it) const
{ {
QSE_ASSERT (this->current != QSE_NULL); QSE_ASSERT (this->current != QSE_NULL);
return this->current != it.current; return this->current != it.current;
@ -143,6 +143,23 @@ public:
return this->current != QSE_NULL; return this->current != QSE_NULL;
} }
T& operator* () // dereference
{
return this->current->getValue();
}
const T& operator* () const // dereference
{
return this->current->getValue();
}
#if 0
T* operator-> ()
{
return &this->current->getValue();
}
#endif
T& getValue () T& getValue ()
{ {
QSE_ASSERT (this->current != QSE_NULL); QSE_ASSERT (this->current != QSE_NULL);
@ -247,14 +264,9 @@ public:
} }
#endif #endif
qse_size_t getMPBlockSize() const Mpool& getMpool ()
{ {
return this->mp.getBlockSize(); return this->mp;
}
bool isMPEnabled () const
{
return this->mp.isEnabled();
} }
qse_size_t getSize () const qse_size_t getSize () const
@ -267,17 +279,15 @@ public:
return this->node_count == 0; return this->node_count == 0;
} }
bool contains (const T& value) const /// The insertNode() function inserts an externally created \a node
{ /// before the node at the given position \a pos. If \a pos is QSE_NULL,
return this->findFirstNode(value) != QSE_NULL; /// the \a node is inserted at the back of the list. You must take extra
} /// care when using this function.
// insert an externally created node.
// may need to take extra care when using this method.
Node* insertNode (Node* pos, Node* node) Node* insertNode (Node* pos, Node* node)
{ {
if (pos == QSE_NULL) if (pos == QSE_NULL)
{ {
// add to the back
if (this->node_count == 0) if (this->node_count == 0)
{ {
QSE_ASSERT (head_node == QSE_NULL); QSE_ASSERT (head_node == QSE_NULL);
@ -293,6 +303,7 @@ public:
} }
else else
{ {
// insert 'node' before the node at the given position 'pos'.
node->next = pos; node->next = pos;
node->prev = pos->prev; node->prev = pos->prev;
if (pos->prev) pos->prev->next = node; if (pos->prev) pos->prev->next = node;
@ -305,59 +316,22 @@ public:
} }
// create a new node to hold the value and insert it. // create a new node to hold the value and insert it.
Node* insertValue (Node* pos, const T& value) Node* insert (Node* pos, const T& value)
{ {
Node* node = new(&this->mp) Node(value); Node* node = new(&this->mp) Node(value);
return this->insertNode (pos, node); return this->insertNode (pos, node);
} }
T& insert (Node* node, const T& value) Node* prepend (const T& value)
{ {
return this->insertValue(node, value)->value;
}
T& insert (qse_size_t index, const T& value)
{
QSE_ASSERT (index <= node_count);
if (index >= node_count)
{
// insert it at the back
return this->insert ((Node*)QSE_NULL, value);
}
return this->insert (this->getNodeAt(index), value);
}
T& prepend (const T& value)
{
// same as prependValue()
return this->insert (this->head_node, value); return this->insert (this->head_node, value);
} }
T& append (const T& value)
Node* append (const T& value)
{ {
// same as appendValue()
return this->insert ((Node*)QSE_NULL, value); return this->insert ((Node*)QSE_NULL, value);
} }
Node* prependNode (Node* node)
{
return this->insertNode (head_node, node);
}
Node* appendNode (Node* node)
{
return this->insertNode ((Node*)QSE_NULL, node);
}
Node* prependValue (const T& value)
{
return this->insertValue (this->head_node, value);
}
Node* appendValue (const T& value)
{
return this->insertValue ((Node*)QSE_NULL, value);
}
void prependAll (const SelfType& list) void prependAll (const SelfType& list)
{ {
Node* n = list.tail_node; Node* n = list.tail_node;
@ -435,6 +409,7 @@ public:
return node; return node;
} }
// remove a node from the list and free it. // remove a node from the list and free it.
void remove (Node* node) void remove (Node* node)
{ {
@ -446,20 +421,6 @@ public:
::operator delete (node, &this->mp); ::operator delete (node, &this->mp);
} }
void remove (qse_size_t index)
{
QSE_ASSERT (index < node_count);
Node* np = this->head_node;
while (index > 0)
{
np = np->next;
index--;
}
this->remove (np);
}
Node* yieldByValue (const T& value, bool clear_links = true) Node* yieldByValue (const T& value, bool clear_links = true)
{ {
Node* p = this->findFirstNode (value); Node* p = this->findFirstNode (value);
@ -611,7 +572,7 @@ public:
qse_size_t findLastIndex (const T& value) const qse_size_t findLastIndex (const T& value) const
{ {
qse_size_t index = node_count; qse_size_t index = this->node_count;
for (Node* p = tail_node; p; p = p->prev) for (Node* p = tail_node; p; p = p->prev)
{ {
index--; index--;
@ -647,10 +608,20 @@ public:
this->mp.dispose (); this->mp.dispose ();
} }
//void reverse () /// The reverse() function reverses the order of nodes.
//{ void reverse ()
// {
//} if (this->node_count > 0)
{
Node* head = this->head_node;
QSE_ASSERT (head != QSE_NULL);
while (head->next)
{
Node* next_node = this->yield (head->next, false);
this->insertNode (this->head_node, next_node);
}
}
}
typedef int (SelfType::*TraverseCallback) (Node* start, Node* cur); typedef int (SelfType::*TraverseCallback) (Node* start, Node* cur);
@ -674,8 +645,16 @@ public:
Iterator getIterator (qse_size_t index = 0) const Iterator getIterator (qse_size_t index = 0) const
{ {
if (this->node_count <= 0)
{
return Iterator (QSE_NULL);
}
else
{
if (index >= this->node_count) index = this->node_count - 1;
return Iterator (this->getNodeAt(index)); return Iterator (this->getNodeAt(index));
} }
}
protected: protected:
MPOOL mp; MPOOL mp;

View File

@ -56,30 +56,33 @@ public:
void dispose (void* ptr); void dispose (void* ptr);
void dispose (); void dispose ();
inline bool isEnabled () const bool isEnabled () const
{ {
return this->datum_size > 0 && this->block_size > 0; return this->datum_size > 0 && this->block_size > 0;
} }
inline bool isDisabled () const
bool isDisabled () const
{ {
return this->datum_size <= 0 || this->block_size <= 0; return this->datum_size <= 0 || this->block_size <= 0;
} }
inline qse_size_t getDatumSize () const qse_size_t getDatumSize () const
{ {
return this->datum_size; return this->datum_size;
} }
inline qse_size_t getBlockSize () const qse_size_t getBlockSize () const
{ {
return this->block_size; return this->block_size;
} }
inline void setBlockSize (qse_size_t blockSize) void setBlockSize (qse_size_t blockSize)
{ {
this->block_size = blockSize; this->block_size = blockSize;
} }
int swap (Mpool& mpool);
#if defined(QSE_DEBUG_MPOOL) #if defined(QSE_DEBUG_MPOOL)
qse_size_t nalloc; qse_size_t nalloc;
qse_size_t navail; qse_size_t navail;
@ -97,6 +100,8 @@ protected:
Chain* next; Chain* next;
}; };
// NOTE: whenever you add new member variables, make sure to
// update the swap() function accordingly
Block* mp_blocks; Block* mp_blocks;
Chain* free_list; Chain* free_list;
qse_size_t datum_size; qse_size_t datum_size;

View File

@ -132,6 +132,50 @@ Mpool::Block* Mpool::add_block ()
return block; return block;
} }
int Mpool::swap (Mpool& mpool)
{
// this function is sensitive to member variables changes.
// whenever you add new member variables, this function require
// relevant changes.
if (this->getMmgr() != mpool.getMmgr())
{
// disallow to swap contents if memory managers are different.
return -1;
}
if (this != &mpool)
{
#if defined(QSE_DEBUG_MPOOL)
qse_size_t org_nalloc = this->nalloc;
qse_size_t org_navail = this->navail;
this->nalloc = mpool.nalloc;
this->navail = mpool.navail;
mpool.nalloc = org_nalloc;
mpool.navail = org_navail;
#endif
Block* org_mp_blocks = this->mp_blocks;
Chain* org_free_list = this->free_list;
qse_size_t org_datum_size = this->datum_size;
qse_size_t org_block_size = this->block_size;
this->mp_blocks = mpool.mp_blocks;
this->free_list = mpool.free_list;
this->datum_size = mpool.datum_size;
this->block_size = mpool.block_size;
mpool.mp_blocks = org_mp_blocks;
mpool.free_list = org_free_list;
mpool.datum_size = org_datum_size;
mpool.block_size = org_block_size;
}
return 0;
}
///////////////////////////////// /////////////////////////////////
QSE_END_NAMESPACE(QSE) QSE_END_NAMESPACE(QSE)
///////////////////////////////// /////////////////////////////////