⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 allocator.hh

📁 Motion JPEG编解码器源代码
💻 HH
字号:
#ifndef __ALLOCATOR_H__#define __ALLOCATOR_H__// This file (C) 2004 Steven Boswell.  All rights reserved.// Released to the public under the GNU General Public License.// See the file COPYING for more information.#include "config.h"#include "mjpeg_types.h"#include "Limits.hh"// An allocator for small classes.  It gets large chunks from the// standard memory allocator & divides it up.  It's able to handle// several different object sizes at once.template <class TYPE, size_t SIZES>class Allocator{public:	Allocator (size_t a_nChunkSize);		// Constructor.  Specify the number of bytes to allocate at a		// time from the standard memory allocator.		~Allocator();		// Destructor.	void *Allocate (size_t a_nSize, size_t a_nBytes);		// Allocate memory for another object of type TYPE.		// Use the given size-bucket, which must be for the given number		// of bytes.		// Returns NULL if memory is exhausted.		void Deallocate (size_t a_nSize, void *a_pMemory);		// Deallocate previously-allocated memory.private:	// One chunk of memory.	class Chunk	{	public:		Chunk *m_pNext;			// The next allocated chunk.		char m_aSpace[];			// The memory to divide up.	};	size_t m_nChunkSize;		// The size of allocated chunks.  Set by the constructor.	Chunk *m_pChunks;		// All the allocated chunks.		char *m_pFreeChunk;		// The next piece of unallocated memory in the		// most-recently-allocated chunk.		void *m_apFree[SIZES];		// Linked lists of freed pieces of memory, for all the sizes we		// manage.	uint32_t m_ulAllocated;		// The number of live allocations, i.e. those that haven't been		// deleted yet.#ifndef NDEBUG	size_t m_aiSizes[SIZES];		// The size of the pieces of memory in each bucket.		// Used to make sure they always ask for the same memory size		// in each bucket.#endif // NDEBUG		void Purge (void);		// Free up all chunks.		// Only safe if there are no live allocations.};// Constructor.  Specify the number of bytes to allocate at a// time from the standard memory allocator.template <class TYPE, size_t SIZES>Allocator<TYPE,SIZES>::Allocator (size_t a_nChunkSize)	: m_pChunks (NULL), m_pFreeChunk (NULL){	// Round our chunk size up to the nearest pointer size.	m_nChunkSize = ((a_nChunkSize + sizeof (Chunk *) - 1)		/ sizeof (Chunk *)) * sizeof (Chunk *);	// All our buckets are empty.	for (size_t i = 0; i < SIZES; ++i)	{		m_apFree[i] = NULL;#ifndef NDEBUG		// (We don't know the memory-size of each bucket yet.)		m_aiSizes[i] = Limits<size_t>::Max;#endif // NDEBUG	}	// No allocations yet.	m_ulAllocated = 0UL;}// Destructor.template <class TYPE, size_t SIZES>Allocator<TYPE,SIZES>::~Allocator(){	// If all allocated objects were deallocated, go ahead and free	// up our memory.  (If there are any allocated objects left, then	// generally, that means this is a global allocator, and since C++	// doesn't guarantee order of destruction for global objects, we	// have no guarantee our clients have been destroyed, and so it	// isn't safe to delete our memory.)	if (m_ulAllocated == 0UL)		Purge();}// Allocate memory for another object of type TYPE.// Use the given size-bucket, which must be for the given number// of bytes.// Returns NULL if memory is exhausted.template <class TYPE, size_t SIZES>void *Allocator<TYPE,SIZES>::Allocate (size_t a_nSize, size_t a_nBytes){	void *pAlloc;		// The memory we allocate.	// Make sure they gave us a valid size.	assert (a_nSize >= 0 && a_nSize < SIZES);	// Make sure they gave us a valid number of bytes.	assert (a_nBytes >= 0);	// Round the number of bytes up to the nearest pointer size.	a_nBytes = ((a_nBytes + sizeof (Chunk *) - 1)		/ sizeof (Chunk *)) * sizeof (Chunk *);#ifndef NDEBUG	// If we don't know the size of this bucket, we do now.	if (m_aiSizes[a_nSize] == Limits<size_t>::Max)		m_aiSizes[a_nSize] = a_nBytes;#endif // NDEBUG	// Make sure they ask for the same number of bytes each time.	assert (m_aiSizes[a_nSize] == a_nBytes);	// If there's a free piece of memory of this size, return it.	if (m_apFree[a_nSize] != NULL)	{		// Remember the allocated memory.		pAlloc = m_apFree[a_nSize];				// Remove it from our list.		m_apFree[a_nSize] = *(void **)m_apFree[a_nSize];		// That's one more allocation.		++m_ulAllocated;		// Return the allocated memory.		return pAlloc;	}	// If there's enough unallocated space in the current chunk,	// use it.	if (m_pFreeChunk != NULL	&& size_t (m_pFreeChunk - ((char *)m_pChunks))		<= m_nChunkSize - a_nBytes)	{		// Remember the allocated memory.		pAlloc = (void *) m_pFreeChunk;		// Move past this new allocated memory.		m_pFreeChunk += a_nBytes;		// That's one more allocation.		++m_ulAllocated;		// Return the allocated memory.		return pAlloc;	}	// We'll have to create a new chunk in order to satisfy this	// allocation request.	// First, find a place for the rest of this chunk.	//	// (Not currently possible, unless we make m_aiSizes[] a non-debug	// thing.)	// Add a new chunk to our list.	{		// Allocate a new chunk.		Chunk *pNewChunk = (Chunk *) new Chunk *			[m_nChunkSize / sizeof (Chunk *)];		if (pNewChunk == NULL)			return NULL;		// Hook it into our list.		pNewChunk->m_pNext = m_pChunks;		m_pChunks = pNewChunk;	}	// The unallocated portion of the new chunk is here.	m_pFreeChunk = m_pChunks->m_aSpace + a_nBytes;	// That's one more allocation.	++m_ulAllocated;	// Return the allocated memory.	return (void *) (&(m_pChunks->m_aSpace));}// Deallocate previously-allocated memory.template <class TYPE, size_t SIZES>voidAllocator<TYPE,SIZES>::Deallocate (size_t a_nSize, void *a_pMemory){	// Make sure they gave us a valid size.	assert (a_nSize >= 0 && a_nSize < SIZES);	// Put this memory into the given bucket.	*(void **)a_pMemory = m_apFree[a_nSize];	m_apFree[a_nSize] = a_pMemory;	// That's one less allocation.	--m_ulAllocated;	// If all memory is unallocated, free up our chunks & start over.	if (m_ulAllocated == 0UL)		Purge();}// Free up all chunks.template <class TYPE, size_t SIZES>voidAllocator<TYPE,SIZES>::Purge (void){	// Make sure there are no live allocations	assert (m_ulAllocated == 0UL);	// Empty the free-space list.	for (size_t i = 0; i < SIZES; ++i)		m_apFree[i] = NULL;	// Free all allocated chunks.	while (m_pChunks != NULL)	{		// Remember the next chunk.		Chunk *pNextChunk = m_pChunks->m_pNext;		// Free this chunk.  (It was allocated as an array of chunk		// pointers.)		delete[] m_pChunks;		// Move to the next chunk.		m_pChunks = pNextChunk;	}}#endif // __ALLOCATOR_H__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -