fixed a bug in void* operator new (qse_size_t size, QSE::Mpool* mp)

removed Mpool from Array
This commit is contained in:
hyung-hwan 2015-03-06 18:24:49 +00:00
parent bdf3e2652d
commit dda5db6257
3 changed files with 83 additions and 82 deletions

View File

@ -28,7 +28,7 @@
#define _QSE_CMN_ARRAY_HPP_ #define _QSE_CMN_ARRAY_HPP_
#include <qse/Types.hpp> #include <qse/Types.hpp>
#include <qse/cmn/Mpool.hpp> #include <qse/cmn/Mmged.hpp>
///////////////////////////////// /////////////////////////////////
QSE_BEGIN_NAMESPACE(QSE) QSE_BEGIN_NAMESPACE(QSE)
@ -48,24 +48,14 @@ struct ArrayResizer
} }
}; };
template<typename T> ///
struct ArrayAssigner /// The Array class provides a dynamically resized array.
{ ///
// The assignment proxy is used to get the value informed of its position template <typename T, typename RESIZER = ArrayResizer >
// within the heap. This default implmentation, however, doesn't utilize
// the position (index).
T& operator() (T& v1, const T& v2, qse_size_t index) const
{
v1 = v2;
return v1;
}
};
template <typename T, typename ASSIGNER = ArrayAssigner<T>, typename RESIZER = ArrayResizer >
class Array: public Mmged class Array: public Mmged
{ {
public: public:
typedef Array<T,ASSIGNER,RESIZER> SelfType; typedef Array<T,RESIZER> SelfType;
enum enum
{ {
@ -73,11 +63,7 @@ public:
INVALID_INDEX = ~(qse_size_t)0 INVALID_INDEX = ~(qse_size_t)0
}; };
Array (Mmgr* mmgr = QSE_NULL, Array (Mmgr* mmgr = QSE_NULL, qse_size_t capacity = DEFAULT_CAPACITY): Mmged (mmgr)
qse_size_t capacity = DEFAULT_CAPACITY,
qse_size_t mpb_size = 0):
Mmged (mmgr),
mp (mmgr, QSE_SIZEOF(T), mpb_size)
{ {
if (capacity <= 0) if (capacity <= 0)
{ {
@ -87,7 +73,7 @@ public:
else else
{ {
//this->buffer = new T[capacity]; //this->buffer = new T[capacity];
this->buffer = (T*)::operator new (capacity * QSE_SIZEOF(*this->buffer), &this->mp); this->buffer = (T*)::operator new (capacity * QSE_SIZEOF(*this->buffer), this->getMmgr());
this->capacity = capacity; this->capacity = capacity;
} }
@ -96,12 +82,11 @@ public:
Array (const SelfType& array): Array (const SelfType& array):
Mmged (array.getMmgr()), Mmged (array.getMmgr()),
mp (array.getMmgr(), array.mp.getDatumSize(), array.mp.getBlockSize()),
count (0), capacity (0), buffer (QSE_NULL) count (0), capacity (0), buffer (QSE_NULL)
{ {
if (array.buffer) if (array.buffer)
{ {
this->buffer = this->clone_buffer (array, array.capacity, array.count); this->buffer = this->clone_buffer (array.buffer, array.capacity, array.count);
this->count = array.count; this->count = array.count;
this->capacity = array.capacity; this->capacity = array.capacity;
} }
@ -125,23 +110,22 @@ public:
} }
protected: protected:
T* clone_buffer (const T* srcbuf, qse_size_t capa, qse_size_t count) T* clone_buffer (const T* srcbuf, qse_size_t capa, qse_size_t cnt)
{ {
QSE_ASSERT (capa > 0); QSE_ASSERT (capa > 0);
QSE_ASSERT (count <= capa); QSE_ASSERT (cnt <= capa);
qse_size_t index; qse_size_t index;
//T* tmp = new T[capa]; //T* tmp = new T[capa];
T* tmp = (T*)::operator new (capa * QSE_SIZEOF(*tmp), &this->mp); T* tmp = (T*)::operator new (capa * QSE_SIZEOF(*tmp), this->getMmgr());
try try
{ {
for (index = 0; index < count; index++) for (index = 0; index < cnt; index++)
{ {
//tmp[index] = srcbuf[index];
// copy-construct each element. // copy-construct each element.
new((QSE::Mpool*)QSE_NULL, &tmp[index]) T(srcbuf[index]); new((QSE::Mmgr*)QSE_NULL, &tmp[index]) T(srcbuf[index]);
} }
} }
catch (...) catch (...)
@ -153,7 +137,7 @@ protected:
--index; --index;
tmp[index].~T (); tmp[index].~T ();
} }
::operator delete (tmp, &this->mp); ::operator delete (tmp, this->getMmgr());
throw; throw;
} }
@ -166,13 +150,12 @@ protected:
{ {
// no value exists in the given position. // no value exists in the given position.
// i can copy-construct the value. // i can copy-construct the value.
new((QSE::Mpool*)QSE_NULL, &this->buffer[index]) T(value); new((QSE::Mmgr*)QSE_NULL, &this->buffer[index]) T(value);
//this->notify_position (this->buffer[index], index);
} }
else else
{ {
// there is an old value in the position. // there is an old value in the position.
this->assigner (this->buffer[index], value, index); this->buffer[index] = value;
} }
} }
@ -212,9 +195,18 @@ public:
return this->buffer; return this->buffer;
} }
/// The getBufferIndex() function returns the index of the /// The getIndex() function returns the index of the given value \a v
/// given value \a v if it is one of the values of the array. /// if it belongs to the array. It returns #INVALID_INDEX if not.
/// It returns #INVALID_INDEX if not. /// Note that this is not a search function.
///
/// \code
/// QSE::Array<int> a;
/// a.insert (0, 10);
/// a.insert (0, 20);
/// a.insert (0, 30);
/// const int& t = a[2];
/// printf ("%lu\n", (unsigned long int)a.getIndex(t)); // print 2
/// \endcode
qse_size_t getIndex (const T& v) qse_size_t getIndex (const T& v)
{ {
if (&v >= &this->buffer[0] && &v < &this->buffer[this->count]) if (&v >= &this->buffer[0] && &v < &this->buffer[this->count])
@ -291,7 +283,7 @@ public:
// fill the gap with a default value. // fill the gap with a default value.
for (qse_size_t i = this->count; i < index; i++) for (qse_size_t i = this->count; i < index; i++)
{ {
new((QSE::Mpool*)QSE_NULL, &this->buffer[i]) T(); new((QSE::Mmgr*)QSE_NULL, &this->buffer[i]) T();
} }
} }
@ -319,8 +311,7 @@ public:
// replace deleted elements by surviving elements at the back // replace deleted elements by surviving elements at the back
while (i < this->count) while (i < this->count)
{ {
//this->buffer[j++] = this->buffer[i++]; this->buffer[j] = this->buffer[i];
this->assigner (this->buffer[j], this->buffer[i], j);
j++; i++; j++; i++;
} }
@ -350,25 +341,18 @@ protected:
} }
public: public:
void clear (bool clear_mpool = false) void clear (bool purge_buffer = false)
{ {
this->clear_all_items (); this->clear_all_items ();
if (clear_mpool) if (purge_buffer && this->buffer)
{ {
if (this->buffer) QSE_ASSERT (this->capacity > 0);
{ ::operator delete (this->buffer, this->getMmgr());
// the buffer has been allocated using the memory pool. this->capacity = 0;
// if the memory pool should be cleared, the buffer must this->buffer = QSE_NULL;
// not be left over either.
QSE_ASSERT (this->capacity > 0);
::operator delete (this->buffer, &this->mp);
this->capacity = 0;
this->buffer = QSE_NULL;
}
QSE_ASSERT (this->capacity == 0); QSE_ASSERT (this->capacity == 0);
this->mp.dispose ();
} }
} }
@ -390,43 +374,48 @@ public:
for (qse_size_t i = this->count; i < size; ++i) for (qse_size_t i = this->count; i < size; ++i)
{ {
// use the default contructor to set the value. // use the default contructor to set the value.
new((QSE::Mpool*)QSE_NULL, &this->buffer[i]) T(); new((QSE::Mmgr*)QSE_NULL, &this->buffer[i]) T();
} }
this->count = size; this->count = size;
} }
} }
void setCapacity (qse_size_t capacity) void setCapacity (qse_size_t capa)
{ {
if (capacity <= 0) if (capa <= 0)
{ {
this->clear (true); this->clear (true);
} }
else else if (this->buffer)
{ {
QSE_ASSERT (this->capacity > 0);
qse_size_t cnt = this->count; qse_size_t cnt = this->count;
if (cnt > capacity) cnt = capacity; if (cnt > capa) cnt = capa;
T* tmp = clone_buffer (*this, capacity, cnt); T* tmp = this->clone_buffer (this->buffer, capa, cnt);
if (this->buffer) // don't call this->clear(true) here. clear items only.
{ this->clear_all_items ();
// don't call this->clear (true) here. clear items only.
// the memory pool may destory the cloned buffer as well.
this->clear_all_items ();
// deallocate the current buffer; // deallocate the current buffer;
::operator delete (this->buffer, &this->mp); ::operator delete (this->buffer, this->getMmgr());
this->capacity = 0; this->capacity = 0;
this->buffer = QSE_NULL; this->buffer = QSE_NULL;
}
this->buffer = tmp; this->buffer = tmp;
this->capacity = capacity; this->capacity = capa;
this->count = cnt; this->count = cnt;
} }
else
{
QSE_ASSERT (this->capacity <= 0);
QSE_ASSERT (this->count <= 0);
this->buffer = (T*)::operator new (capa * QSE_SIZEOF(*this->buffer), this->getMmgr());
this->capacity = capa;
}
} }
void trimToSize () void trimToSize ()
@ -488,31 +477,25 @@ public:
{ {
last = first + nk; last = first + nk;
index = first; index = first;
//c = this->buffer[first]; c = this->buffer[first];
this->assigner (c, this->buffer[first], INVALID_INDEX);
while (1) while (1)
{ {
cnt++; cnt++;
while (index < nk) while (index < nk)
{ {
//this->buffer[index] = this->buffer[index + n]; this->buffer[index] = this->buffer[index + n];
this->assigner (this->buffer[index], this->buffer[index + n], index);
index += n; index += n;
} }
if (index == last) break; if (index == last) break;
//this->buffer[index] = this->buffer[index - nk]; this->buffer[index] = this->buffer[index - nk];
this->assigner (this->buffer[index], this->buffer[index - nk], index);
index -= nk; index -= nk;
} }
//this->buffer[last] = c; this->buffer[last] = c;
this->assigner (this->buffer[last], c, last);
first++; first++;
} }
} }
protected: protected:
Mpool mp;
ASSIGNER assigner;
RESIZER resizer; RESIZER resizer;
qse_size_t count; qse_size_t count;

View File

@ -55,6 +55,7 @@ public:
typedef qse_mmgr_t mmgr_t; typedef qse_mmgr_t mmgr_t;
QSE_EXCEPTION (MemoryError); QSE_EXCEPTION (MemoryError);
QSE_EXCEPTION (InvalidArgumentError);
protected: protected:
bool raise_exception; bool raise_exception;

View File

@ -182,7 +182,24 @@ QSE_END_NAMESPACE(QSE)
void* operator new (qse_size_t size, QSE::Mpool* mp) void* operator new (qse_size_t size, QSE::Mpool* mp)
{ {
return mp->isEnabled()? mp->allocate(): ::operator new(size, mp->getMmgr()); if (mp->isEnabled())
{
QSE_ASSERT (size == mp->getDatumSize());
// the size argument is not really used. you must make sure that
// the given size matches the datum size of the memory pool.
if (size != mp->getDatumSize())
{
//QSE::Mmgr* mmgr = mp->getMmgr();
QSE_THROW (QSE::Mmgr::InvalidArgumentError);
}
return mp->allocate ();
}
else
{
// but when the memory pool is not enabled, it goes through
// the memory manager directly and it honors the size argument.
return ::operator new(size, mp->getMmgr());
}
} }
void operator delete (void* ptr, QSE::Mpool* mp) void operator delete (void* ptr, QSE::Mpool* mp)