added Mpool and LinkedList
This commit is contained in:
583
qse/include/qse/cmn/LinkedList.hpp
Normal file
583
qse/include/qse/cmn/LinkedList.hpp
Normal file
@ -0,0 +1,583 @@
|
||||
/*
|
||||
* $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_LINKEDLIST_HPP_
|
||||
#define _QSE_CMN_LINKEDLIST_HPP_
|
||||
|
||||
#include <qse/Types.hpp>
|
||||
#include <xp/bas/MemoryPool.hpp>
|
||||
#include <xp/bas/MemoryPoolable.hpp>
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
template <typename T> class LinkedList;
|
||||
|
||||
template <typename T>
|
||||
class LinkedListNode: protected MemoryPoolable
|
||||
{
|
||||
public:
|
||||
friend class LinkedList<T>;
|
||||
|
||||
T value;
|
||||
|
||||
protected:
|
||||
LinkedListNode<T>* next;
|
||||
LinkedListNode<T>* prev;
|
||||
|
||||
public:
|
||||
LinkedListNode<T>* getNext () { return this->next; }
|
||||
const LinkedListNode<T>* getNext () const { return this->next; }
|
||||
|
||||
LinkedListNode<T>* getPrev () { return this->prev; }
|
||||
const LinkedListNode<T>* getPrev () const { return this->prev; }
|
||||
|
||||
protected:
|
||||
LinkedListNode () {}
|
||||
LinkedListNode (const T& v): value(v) {}
|
||||
|
||||
void setNext (const LinkedListNode<T>* node)
|
||||
{
|
||||
this->next = node;
|
||||
}
|
||||
void setPrev (const LinkedListNode<T>* node)
|
||||
{
|
||||
this->prev = node;
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// The LinkedList<T> class provides a template for a doubly-linked list.
|
||||
///
|
||||
template <typename T> class LinkedList
|
||||
{
|
||||
public:
|
||||
typedef LinkedListNode<T> Node;
|
||||
|
||||
enum
|
||||
{
|
||||
INVALID_INDEX = ~(qse_size_t)0
|
||||
};
|
||||
|
||||
~LinkedList ()
|
||||
{
|
||||
this->clearout ();
|
||||
}
|
||||
|
||||
LinkedList (qse_size_t mpb_size = 0): mp (QSE_SIZEOF(Node), mpb_size)
|
||||
{
|
||||
this->node_count = 0;
|
||||
this->head_node = QSE_NULL;
|
||||
this->tail_node = QSE_NULL;
|
||||
}
|
||||
|
||||
LinkedList (const LinkedList<T>& ll): mp (ll.mp.datumSize(), ll.mp.blockSize())
|
||||
{
|
||||
this->node_count = 0;
|
||||
this->head_node = QSE_NULL;
|
||||
this->tail_node = QSE_NULL;
|
||||
for (Node* p = ll.head_node; p != QSE_NULL; p = p->next)
|
||||
this->append (p->value);
|
||||
}
|
||||
|
||||
LinkedList<T>& operator= (const LinkedList<T>& ll)
|
||||
{
|
||||
this->clear ();
|
||||
for (Node* p = ll.head_node; p != QSE_NULL; p = p->next)
|
||||
this->append (p->value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator[] (qse_size_t index)
|
||||
{
|
||||
// same as getValueAt()
|
||||
QSE_ASSERT (index < this->node_count);
|
||||
Node* np = this->getNodeAt (index);
|
||||
return np->value;
|
||||
}
|
||||
|
||||
const T& operator[] (qse_size_t index) const
|
||||
{
|
||||
// same as getValueAt()
|
||||
QSE_ASSERT (index < this->node_count);
|
||||
Node* np = this->getNodeAt (index);
|
||||
return np->value;
|
||||
}
|
||||
|
||||
qse_size_t getMPBlockSize() const
|
||||
{
|
||||
return this->mp.blockSize();
|
||||
}
|
||||
|
||||
bool isMPEnabled () const
|
||||
{
|
||||
return this->mp.isEnabled();
|
||||
}
|
||||
|
||||
qse_size_t getSize () const
|
||||
{
|
||||
return this->node_count;
|
||||
}
|
||||
|
||||
bool isEmpty () const
|
||||
{
|
||||
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.
|
||||
Node* insertNode (Node* pos, Node* node);
|
||||
|
||||
// create a new node to hold the value and insert it.
|
||||
Node* insertValue (Node* pos, const T& value)
|
||||
{
|
||||
Node* n = this->mp.isEnabled()?
|
||||
(new(&mp) Node(value)): (new Node(value));
|
||||
return this->insertNode (pos, n);
|
||||
}
|
||||
|
||||
T& insert (Node* node, 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)
|
||||
{
|
||||
return this->insert (this->head_node, value);
|
||||
}
|
||||
T& append (const T& 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 LinkedList<T>& list)
|
||||
{
|
||||
Node* n = list.tail_node;
|
||||
|
||||
if (&list == this)
|
||||
{
|
||||
Node* head = list.head_node;
|
||||
while (n)
|
||||
{
|
||||
this->prepend (n->value);
|
||||
if (n == head) break;
|
||||
n = (Node*)n->prev;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (n)
|
||||
{
|
||||
this->prepend (n->value);
|
||||
n = (Node*)n->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appendAll (const LinkedList<T>& list)
|
||||
{
|
||||
Node* n = list.head_node;
|
||||
|
||||
if (&list == this)
|
||||
{
|
||||
Node* tail = list.tail_node;
|
||||
while (n)
|
||||
{
|
||||
this->append (n->value);
|
||||
if (n == tail) break;
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (n)
|
||||
{
|
||||
this->append (n->value);
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove a node from the list without freeing it.
|
||||
// take extra care when using this method as the node
|
||||
// can be freed through the memory pool when the list is
|
||||
// destructed if the memory pool is enabled.
|
||||
Node* yield (Node* node, bool clear_links = true);
|
||||
|
||||
// remove a node from the list and free it.
|
||||
void remove (Node* node)
|
||||
{
|
||||
this->yield (node, false);
|
||||
if (mp.isDisabled()) delete node;
|
||||
else
|
||||
{
|
||||
node->~Node ();
|
||||
#if defined(_MSC_VER)
|
||||
node->operator delete (node, &mp);
|
||||
#else
|
||||
node->dispose (node, &mp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
Node* p = this->findFirstNode (value);
|
||||
if (p == QSE_NULL) return -1;
|
||||
return this->yield (p, clear_links);
|
||||
}
|
||||
|
||||
qse_size_t removeByValue (const T& value)
|
||||
{
|
||||
Node* p = this->findFirstNode (value);
|
||||
if (!p) return 0;
|
||||
this->remove (p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// \return the number of items deleted
|
||||
qse_size_t removeAllByValue (const T& value)
|
||||
{
|
||||
Node* p = this->findFirstNode (value);
|
||||
if (!p) return 0;
|
||||
|
||||
qse_size_t cnt = 0;
|
||||
do
|
||||
{
|
||||
Node* tmp = p->next;
|
||||
this->remove (p);
|
||||
cnt++;
|
||||
p = this->findFirstNode (value, tmp);
|
||||
}
|
||||
while (p);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void removeHead ()
|
||||
{
|
||||
this->remove (this->head_node);
|
||||
}
|
||||
void removeTail ()
|
||||
{
|
||||
this->remove (this->tail_node);
|
||||
}
|
||||
|
||||
Node* getHeadNode () const
|
||||
{
|
||||
return this->head_node;
|
||||
}
|
||||
|
||||
Node* getTailNode () const
|
||||
{
|
||||
return this->tail_node;
|
||||
}
|
||||
|
||||
Node* getNodeAt (qse_size_t index) const
|
||||
{
|
||||
QSE_ASSERT (index < this->node_count);
|
||||
|
||||
register Node* np;
|
||||
register qse_size_t cnt;
|
||||
|
||||
if (index < (this->node_count >> 1))
|
||||
{
|
||||
for (np = this->head_node, cnt = 0; cnt < index; np = np->next, cnt++)
|
||||
{
|
||||
QSE_ASSERT (np != QSE_NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (np = this->tail_node, cnt = this->node_count - 1; cnt > index; np = np->prev, cnt--)
|
||||
{
|
||||
QSE_ASSERT (np != QSE_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return np;
|
||||
}
|
||||
|
||||
T& getValueAt (qse_size_t index)
|
||||
{
|
||||
// same as operator[]
|
||||
QSE_ASSERT (index < this->node_count);
|
||||
Node* np = this->getNodeAt (index);
|
||||
return np->value;
|
||||
}
|
||||
|
||||
const T& getValueAt (qse_size_t index) const
|
||||
{
|
||||
// same as operator[]
|
||||
QSE_ASSERT (index < this->node_count);
|
||||
Node* np = this->getNodeAt (index);
|
||||
return np->value;
|
||||
}
|
||||
|
||||
void setValueAt (qse_size_t index, const T& value)
|
||||
{
|
||||
QSE_ASSERT (index < this->node_count);
|
||||
Node* np = this->getNodeAt (index);
|
||||
np->value = value;
|
||||
}
|
||||
|
||||
Node* findFirstNode (const T& value) const
|
||||
{
|
||||
for (Node* p = this->head_node; p; p = p->next)
|
||||
{
|
||||
if (value == p->value) return p;
|
||||
}
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
Node* findLastNode (const T& value) const
|
||||
{
|
||||
for (Node* p = tail_node; p; p = p->prev)
|
||||
{
|
||||
if (value == p->value) return p;
|
||||
}
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
Node* findFirstNode (const T& value, Node* head) const
|
||||
{
|
||||
for (Node* p = head; p; p = p->next)
|
||||
{
|
||||
if (value == p->value) return p;
|
||||
}
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
Node* findLastNode (const T& value, Node* tail) const
|
||||
{
|
||||
for (Node* p = tail; p; p = p->prev)
|
||||
{
|
||||
if (value == p->value) return p;
|
||||
}
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_size_t findFirstIndex (const T& value) const
|
||||
{
|
||||
qse_size_t index = 0;
|
||||
for (Node* p = this->head_node; p; p = p->next)
|
||||
{
|
||||
if (value == p->value) return index;
|
||||
index++;
|
||||
}
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
qse_size_t findLastIndex (const T& value) const
|
||||
{
|
||||
qse_size_t index = node_count;
|
||||
for (Node* p = tail_node; p; p = p->prev)
|
||||
{
|
||||
index--;
|
||||
if (value == p->value) return index;
|
||||
}
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
Node* p, * saved;
|
||||
|
||||
p = this->head_node;
|
||||
while (p)
|
||||
{
|
||||
saved = p->next;
|
||||
|
||||
if (this->mp.isDisabled()) delete p;
|
||||
else
|
||||
{
|
||||
p->~Node ();
|
||||
#if defined(_MSC_VER)
|
||||
p->operator delete (p, &mp);
|
||||
#else
|
||||
p->dispose (p, &mp);
|
||||
#endif
|
||||
}
|
||||
|
||||
this->node_count--;
|
||||
p = saved;
|
||||
}
|
||||
|
||||
this->head_node = this->tail_node = QSE_NULL;
|
||||
QSE_ASSERT (this->node_count == 0);
|
||||
}
|
||||
|
||||
void clearout ()
|
||||
{
|
||||
this->clear ();
|
||||
this->mp.dispose ();
|
||||
}
|
||||
|
||||
typedef int (LinkedList<T>::*TraverseCallback) (Node* start, Node* cur);
|
||||
|
||||
void traverse (TraverseCallback callback, Node* start)
|
||||
{
|
||||
Node* cur, * prev, * next;
|
||||
|
||||
cur = start;
|
||||
while (cur)
|
||||
{
|
||||
prev = cur->prev;
|
||||
next = cur->next;
|
||||
|
||||
int n = (this->*callback) (start, cur);
|
||||
|
||||
if (n > 0) cur = next;
|
||||
else if (n < 0) cur = prev;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
MemoryPool mp;
|
||||
Node* head_node;
|
||||
Node* tail_node;
|
||||
qse_size_t node_count;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline typename LinkedList<T>::Node* LinkedList<T>::insertNode (Node* pos, Node* node)
|
||||
{
|
||||
if (pos == QSE_NULL)
|
||||
{
|
||||
if (this->node_count == 0)
|
||||
{
|
||||
QSE_ASSERT (head_node == QSE_NULL);
|
||||
QSE_ASSERT (tail_node == QSE_NULL);
|
||||
this->head_node = this->tail_node = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->prev = this->tail_node;
|
||||
this->tail_node->next = node;
|
||||
this->tail_node = node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
node->next = pos;
|
||||
node->prev = pos->prev;
|
||||
if (pos->prev) pos->prev->next = node;
|
||||
else this->head_node = node;
|
||||
pos->prev = node;
|
||||
}
|
||||
|
||||
this->node_count++;
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename LinkedList<T>::Node* LinkedList<T>::yield (Node* node, bool clear_links)
|
||||
{
|
||||
QSE_ASSERT (node != QSE_NULL);
|
||||
QSE_ASSERT (this->node_count > 0);
|
||||
|
||||
if (node->next)
|
||||
node->next->prev = node->next;
|
||||
else
|
||||
this->tail_node = node->prev;
|
||||
|
||||
if (node->prev)
|
||||
node->prev->next = node->next;
|
||||
else
|
||||
this->head_node = node->next;
|
||||
|
||||
this->node_count--;
|
||||
|
||||
if (clear_links)
|
||||
{
|
||||
node->next = QSE_NULL;
|
||||
node->prev = QSE_NULL;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -50,6 +50,8 @@ pkginclude_HEADERS = \
|
||||
xma.h
|
||||
|
||||
if ENABLE_CXX
|
||||
pkginclude_HEADERS += Mmgr.hpp StdMmgr.hpp Mmged.hpp
|
||||
pkginclude_HEADERS += \
|
||||
Mmgr.hpp StdMmgr.hpp Mmged.hpp Mpool.hpp Mpoolable.hpp \
|
||||
LinkedList.hpp
|
||||
endif
|
||||
|
||||
|
@ -50,7 +50,10 @@ PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
@ENABLE_CXX_TRUE@am__append_1 = Mmgr.hpp StdMmgr.hpp Mmged.hpp
|
||||
@ENABLE_CXX_TRUE@am__append_1 = \
|
||||
@ENABLE_CXX_TRUE@ Mmgr.hpp StdMmgr.hpp Mmged.hpp Mpool.hpp Mpoolable.hpp \
|
||||
@ENABLE_CXX_TRUE@ LinkedList.hpp
|
||||
|
||||
subdir = include/qse/cmn
|
||||
DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in
|
||||
@ -87,7 +90,8 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dir.h dll.h \
|
||||
lda.h main.h map.h mb8.h mbwc.h mem.h mux.h nwad.h nwif.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 Mmged.hpp
|
||||
utf8.h xma.h Mmgr.hpp StdMmgr.hpp Mmged.hpp Mpool.hpp \
|
||||
Mpoolable.hpp LinkedList.hpp
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
|
107
qse/include/qse/cmn/Mpool.hpp
Normal file
107
qse/include/qse/cmn/Mpool.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* $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_MPOOL_HPP_
|
||||
#define _QSE_CMN_MPOOL_HPP_
|
||||
|
||||
#include <qse/Uncopyable.hpp>
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
//
|
||||
// allocator for fixed-size data
|
||||
//
|
||||
|
||||
class Mpool: public Uncopyable
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
DEFAULT_BLOCK_SIZE = 128
|
||||
};
|
||||
|
||||
Mpool (
|
||||
qse_size_t datum_size,
|
||||
qse_size_t block_size = DEFAULT_BLOCK_SIZE);
|
||||
~Mpool ();
|
||||
|
||||
void* allocate ();
|
||||
void dispose (void* ptr);
|
||||
void dispose ();
|
||||
|
||||
inline bool isEnabled () const
|
||||
{
|
||||
return this->datum_size > 0 && this->block_size > 0;
|
||||
}
|
||||
inline bool isDisabled () const
|
||||
{
|
||||
return this->datum_size <= 0 || this->block_size <= 0;
|
||||
}
|
||||
|
||||
inline qse_size_t datumSize () const
|
||||
{
|
||||
return this->datum_size;
|
||||
}
|
||||
inline qse_size_t blockSize () const
|
||||
{
|
||||
return this->block_size;
|
||||
}
|
||||
inline void setBlockSize (qse_size_t blockSize)
|
||||
{
|
||||
this->block_size = blockSize;
|
||||
}
|
||||
|
||||
#if defined(QSE_DEBUG_MPOOL)
|
||||
qse_size_t nalloc;
|
||||
qse_size_t navail;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
struct Block
|
||||
{
|
||||
Block* next;
|
||||
//qse_uint8_t data[0];
|
||||
};
|
||||
struct Chain
|
||||
{
|
||||
Chain* next;
|
||||
};
|
||||
|
||||
Block* mp_blocks;
|
||||
Chain* free_list;
|
||||
qse_size_t datum_size;
|
||||
qse_size_t block_size;
|
||||
|
||||
void add_block ();
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
////////////////////////////////
|
||||
#endif
|
||||
|
73
qse/include/qse/cmn/Mpoolable.hpp
Normal file
73
qse/include/qse/cmn/Mpoolable.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* $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_MPOOLABLE_HPP_
|
||||
#define _QSE_CMN_MPOOLABLE_HPP_
|
||||
|
||||
#include <qse/cmn/Mpool.hpp>
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
class Mpoolable
|
||||
{
|
||||
public:
|
||||
typedef qse_size_t mp_size_t;
|
||||
|
||||
inline void* operator new (mp_size_t size)
|
||||
{
|
||||
return ::operator new (size);
|
||||
}
|
||||
|
||||
inline void operator delete (void* ptr)
|
||||
{
|
||||
::operator delete (ptr);
|
||||
}
|
||||
|
||||
inline void* operator new (mp_size_t /*size*/, Mpool* mp)
|
||||
{
|
||||
return mp->allocate ();
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
void operator delete (void* ptr, Mpool* mp)
|
||||
{
|
||||
mp->dispose (ptr);
|
||||
}
|
||||
#else
|
||||
inline void dispose (void* ptr, Mpool* mp)
|
||||
{
|
||||
mp->dispose (ptr);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_END_NAMESPACE(QSE)
|
||||
/////////////////////////////////
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user