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 ();
}
Mpool& getMpool ()
{
return this->datum_list->getMpool ();
}
SelfType& operator= (const SelfType& list)
{
this->clear ();
@ -301,12 +306,12 @@ protected:
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];
}
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];
@ -467,7 +472,13 @@ protected:
// 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->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();
while (p)
{
@ -491,7 +502,7 @@ protected:
}
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];
}
@ -507,7 +518,13 @@ protected:
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;
Node** temp_nodes = temp.nodes;
DatumList* temp_datum_list = temp.datum_list;
@ -539,12 +556,12 @@ protected:
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];
}
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
protected:
SelfType* next;
SelfType* prev;
SelfType* next;
public:
T& getValue () { return this->value; }
@ -126,13 +126,13 @@ public:
return saved;
}
int operator== (const SelfType& it) const
bool operator== (const SelfType& it) const
{
QSE_ASSERT (this->current != QSE_NULL);
return this->current == it.current;
}
int operator!= (const SelfType& it) const
bool operator!= (const SelfType& it) const
{
QSE_ASSERT (this->current != QSE_NULL);
return this->current != it.current;
@ -143,6 +143,23 @@ public:
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 ()
{
QSE_ASSERT (this->current != QSE_NULL);
@ -247,14 +264,9 @@ public:
}
#endif
qse_size_t getMPBlockSize() const
Mpool& getMpool ()
{
return this->mp.getBlockSize();
}
bool isMPEnabled () const
{
return this->mp.isEnabled();
return this->mp;
}
qse_size_t getSize () const
@ -267,17 +279,15 @@ public:
return this->node_count == 0;
}
bool contains (const T& value) const
{
return this->findFirstNode(value) != QSE_NULL;
}
// insert an externally created node.
// may need to take extra care when using this method.
/// The insertNode() function inserts an externally created \a node
/// before the node at the given position \a pos. If \a pos is QSE_NULL,
/// the \a node is inserted at the back of the list. You must take extra
/// care when using this function.
Node* insertNode (Node* pos, Node* node)
{
if (pos == QSE_NULL)
{
// add to the back
if (this->node_count == 0)
{
QSE_ASSERT (head_node == QSE_NULL);
@ -293,6 +303,7 @@ public:
}
else
{
// insert 'node' before the node at the given position 'pos'.
node->next = pos;
node->prev = pos->prev;
if (pos->prev) pos->prev->next = node;
@ -305,59 +316,22 @@ public:
}
// 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);
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);
}
T& append (const T& value)
Node* append (const T& value)
{
// same as appendValue()
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)
{
Node* n = list.tail_node;
@ -435,6 +409,7 @@ public:
return node;
}
// remove a node from the list and free it.
void remove (Node* node)
{
@ -446,20 +421,6 @@ public:
::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* p = this->findFirstNode (value);
@ -611,7 +572,7 @@ public:
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)
{
index--;
@ -647,10 +608,20 @@ public:
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);
@ -674,8 +645,16 @@ public:
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));
}
}
protected:
MPOOL mp;

View File

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

View File

@ -132,6 +132,50 @@ Mpool::Block* Mpool::add_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)
/////////////////////////////////