fixed a bug in void* operator new (qse_size_t size, QSE::Mpool* mp)
removed Mpool from Array
This commit is contained in:
		| @ -28,7 +28,7 @@ | ||||
| #define _QSE_CMN_ARRAY_HPP_ | ||||
|  | ||||
| #include <qse/Types.hpp> | ||||
| #include <qse/cmn/Mpool.hpp> | ||||
| #include <qse/cmn/Mmged.hpp> | ||||
|  | ||||
| ///////////////////////////////// | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| @ -48,24 +48,14 @@ struct ArrayResizer | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| template<typename T> | ||||
| struct ArrayAssigner | ||||
| { | ||||
| 	// The assignment proxy is used to get the value informed of its position | ||||
| 	// 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 > | ||||
| /// | ||||
| /// The Array class provides a dynamically resized array. | ||||
| ///  | ||||
| template <typename T, typename RESIZER = ArrayResizer > | ||||
| class Array: public Mmged | ||||
| { | ||||
| public: | ||||
| 	typedef Array<T,ASSIGNER,RESIZER> SelfType; | ||||
| 	typedef Array<T,RESIZER> SelfType; | ||||
|  | ||||
| 	enum  | ||||
| 	{ | ||||
| @ -73,11 +63,7 @@ public: | ||||
| 		INVALID_INDEX = ~(qse_size_t)0 | ||||
| 	}; | ||||
|  | ||||
| 	Array (Mmgr* mmgr = QSE_NULL, | ||||
| 	       qse_size_t capacity = DEFAULT_CAPACITY,  | ||||
| 	       qse_size_t mpb_size = 0): | ||||
| 		Mmged (mmgr), | ||||
| 		mp (mmgr, QSE_SIZEOF(T), mpb_size) | ||||
| 	Array (Mmgr* mmgr = QSE_NULL, qse_size_t capacity = DEFAULT_CAPACITY): Mmged (mmgr) | ||||
| 	{ | ||||
| 		if (capacity <= 0)  | ||||
| 		{ | ||||
| @ -87,7 +73,7 @@ public: | ||||
| 		else  | ||||
| 		{ | ||||
| 			//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; | ||||
| 		} | ||||
|  | ||||
| @ -96,12 +82,11 @@ public: | ||||
|  | ||||
| 	Array (const SelfType& array):  | ||||
| 		Mmged (array.getMmgr()), | ||||
| 		mp (array.getMmgr(), array.mp.getDatumSize(), array.mp.getBlockSize()), | ||||
| 		count (0), capacity (0), buffer (QSE_NULL) | ||||
| 	{ | ||||
| 		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->capacity = array.capacity; | ||||
| 		} | ||||
| @ -125,23 +110,22 @@ public: | ||||
| 	} | ||||
|  | ||||
| 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 (count <= capa); | ||||
| 		QSE_ASSERT (cnt <= capa); | ||||
|  | ||||
| 		qse_size_t index; | ||||
|  | ||||
| 		//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  | ||||
| 		{ | ||||
| 			for (index = 0; index < count; index++)  | ||||
| 			for (index = 0; index < cnt; index++)  | ||||
| 			{ | ||||
| 				//tmp[index] = srcbuf[index]; | ||||
| 				// 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 (...)  | ||||
| @ -153,7 +137,7 @@ protected: | ||||
| 				--index; | ||||
| 				tmp[index].~T (); | ||||
| 			} | ||||
| 			::operator delete (tmp, &this->mp); | ||||
| 			::operator delete (tmp, this->getMmgr()); | ||||
| 			throw; | ||||
| 		} | ||||
|  | ||||
| @ -166,13 +150,12 @@ protected: | ||||
| 		{ | ||||
| 			// no value exists in the given position. | ||||
| 			// i can copy-construct the value. | ||||
| 			new((QSE::Mpool*)QSE_NULL, &this->buffer[index]) T(value); | ||||
| 			//this->notify_position (this->buffer[index], index); | ||||
| 			new((QSE::Mmgr*)QSE_NULL, &this->buffer[index]) T(value); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// 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; | ||||
| 	} | ||||
|  | ||||
| 	/// The getBufferIndex() function returns the index of the | ||||
| 	/// given value \a v if it is one of the values of the array. | ||||
| 	/// It returns #INVALID_INDEX if not. | ||||
| 	/// The getIndex() function returns the index of the given value \a v  | ||||
| 	/// if it belongs to the array. 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) | ||||
| 	{ | ||||
| 		if (&v >= &this->buffer[0] && &v < &this->buffer[this->count]) | ||||
| @ -291,7 +283,7 @@ public: | ||||
| 			// fill the gap with a default value. | ||||
| 			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 | ||||
| 		while (i < this->count)  | ||||
| 		{ | ||||
| 			//this->buffer[j++] = this->buffer[i++]; | ||||
| 			this->assigner (this->buffer[j], this->buffer[i], j); | ||||
| 			this->buffer[j] = this->buffer[i]; | ||||
| 			j++; i++; | ||||
| 		} | ||||
|  | ||||
| @ -350,25 +341,18 @@ protected: | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| 	void clear (bool clear_mpool = false) | ||||
| 	void clear (bool purge_buffer = false) | ||||
| 	{ | ||||
| 		this->clear_all_items (); | ||||
|  | ||||
| 		if (clear_mpool)  | ||||
| 		if (purge_buffer && this->buffer) | ||||
| 		{ | ||||
| 			if (this->buffer) | ||||
| 			{ | ||||
| 				// the buffer has been allocated using the memory pool. | ||||
| 				// if the memory pool should be cleared, the buffer must | ||||
| 				// not be left over either. | ||||
| 			QSE_ASSERT (this->capacity > 0); | ||||
| 				::operator delete (this->buffer, &this->mp); | ||||
| 			::operator delete (this->buffer, this->getMmgr()); | ||||
| 			this->capacity = 0; | ||||
| 			this->buffer = QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			QSE_ASSERT (this->capacity == 0); | ||||
| 			this->mp.dispose (); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -390,43 +374,48 @@ public: | ||||
| 			for (qse_size_t i = this->count; i < size; ++i) | ||||
| 			{ | ||||
| 				// 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; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void setCapacity (qse_size_t capacity) | ||||
| 	void setCapacity (qse_size_t capa) | ||||
| 	{ | ||||
| 		if (capacity <= 0)  | ||||
| 		if (capa <= 0)  | ||||
| 		{ | ||||
| 			this->clear (true); | ||||
| 		} | ||||
| 		else  | ||||
| 		else if (this->buffer) | ||||
| 		{ | ||||
| 			QSE_ASSERT (this->capacity > 0); | ||||
|  | ||||
| 			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. | ||||
| 				// the memory pool may destory the cloned buffer as well. | ||||
| 			// don't call this->clear(true) here. clear items only. | ||||
| 			this->clear_all_items (); | ||||
|  | ||||
| 			// deallocate the current buffer; | ||||
| 				::operator delete (this->buffer, &this->mp); | ||||
| 			::operator delete (this->buffer, this->getMmgr()); | ||||
| 			this->capacity = 0; | ||||
| 			this->buffer = QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			this->buffer = tmp; | ||||
| 			this->capacity = capacity; | ||||
| 			this->capacity = capa; | ||||
| 			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 () | ||||
| @ -488,31 +477,25 @@ public: | ||||
| 		{ | ||||
| 			last = first + nk; | ||||
| 			index = first; | ||||
| 			//c = this->buffer[first]; | ||||
| 			this->assigner (c, this->buffer[first], INVALID_INDEX); | ||||
| 			c = this->buffer[first]; | ||||
| 			while (1)  | ||||
| 			{ | ||||
| 				cnt++; | ||||
| 				while (index < nk)  | ||||
| 				{ | ||||
| 					//this->buffer[index] = this->buffer[index + n]; | ||||
| 					this->assigner (this->buffer[index], this->buffer[index + n], index); | ||||
| 					this->buffer[index] = this->buffer[index + n]; | ||||
| 					index += n; | ||||
| 				} | ||||
| 				if (index == last) break; | ||||
| 				//this->buffer[index] = this->buffer[index - nk]; | ||||
| 				this->assigner (this->buffer[index], this->buffer[index - nk], index); | ||||
| 				this->buffer[index] = this->buffer[index - nk]; | ||||
| 				index -= nk; | ||||
| 			} | ||||
| 			//this->buffer[last] = c;  | ||||
| 			this->assigner (this->buffer[last], c, last); | ||||
| 			this->buffer[last] = c; | ||||
| 			first++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| protected: | ||||
| 	Mpool      mp; | ||||
| 	ASSIGNER   assigner; | ||||
| 	RESIZER    resizer; | ||||
|  | ||||
| 	qse_size_t count; | ||||
|  | ||||
| @ -55,6 +55,7 @@ public: | ||||
| 	typedef qse_mmgr_t mmgr_t; | ||||
|  | ||||
| 	QSE_EXCEPTION (MemoryError); | ||||
| 	QSE_EXCEPTION (InvalidArgumentError); | ||||
|  | ||||
| protected: | ||||
| 	bool raise_exception; | ||||
|  | ||||
| @ -182,7 +182,24 @@ QSE_END_NAMESPACE(QSE) | ||||
|  | ||||
| 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) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user