動態擴展buffer block

#pragma  once
#include <corecrt_memory.h>
#include <list>
#include <mutex>

#define BLOCK_BUFFER_SIZE   4096
#define INIT_BLOCK_SIZE     2
class CBlock
{
public:
	CBlock() :
		_headOffset(0),
		_tailOffset(0)
	{}
	~CBlock() {}

	static CBlock* create()
	{
		return new CBlock;
	}
	void destroy()
	{
		delete this;
	}
	int write(char* buffer, int size)
	{
		int remaindSize = getRemaindSize();
		int copySize = size > remaindSize ? remaindSize : size;
		memcpy(_buffer + _tailOffset, buffer, copySize);
		return copySize;
	}

	int read(char* buffer, int size)
	{
		int useSize = getUseSize();
		int copySize = size > useSize ? useSize : size;
		memcpy(buffer,_buffer + _headOffset , copySize);
		return copySize;
	}
	int getUseSize()
	{
		return _tailOffset - _headOffset;
	}
	int getRemaindSize()
	{
		return BLOCK_BUFFER_SIZE - _tailOffset;
	}
	bool empty()
	{
		return _headOffset == _tailOffset;
	}
	bool full()
	{
		return  _tailOffset >= BLOCK_BUFFER_SIZE;
	}
	void clear()
	{
		_headOffset = 0;
		_tailOffset = 0;
	}
	void setHeadOffset(int offset)
	{
		_headOffset += offset;
	}
	void setTailOffset(int offset)
	{
		_tailOffset += offset;
	}
private:
	int _headOffset;
	int _tailOffset;
	char _buffer[BLOCK_BUFFER_SIZE];
};


class CBlockBuffer
{
public:
	CBlockBuffer(int initSize = INIT_BLOCK_SIZE);
	~CBlockBuffer();
	static CBlockBuffer* create()
	{
		return new CBlockBuffer;
	}
	void destroy();

	int  write(char* buffer,int totalSize);

	int  read(char* buffer, int totalSize);

	int  readNotMove(char* buffer, int totalSize);

	void reset();

	std::mutex& getMutex() { return _mx; }

	int getUseSize() { return m_useSize; }
private:
	CBlock* allocBlock();
private:
	std::list<CBlock*>  m_useBlockList;
	std::list<CBlock*>  m_freeBlockList;
	int m_useSize;
	std::mutex _mx;
};

#include "BlockBuffer.h"

CBlockBuffer::CBlockBuffer(int initSize)
	:m_useSize(0)
{
	m_useBlockList.clear();
	m_freeBlockList.clear();

	for (int index = 0 ;index < initSize; ++index)
	{
		CBlock* block = CBlock::create();
		if (block)
		{
			m_freeBlockList.push_back(block);
		}
	}
}

void CBlockBuffer::destroy()
{
	while (!m_useBlockList.empty())
	{
		CBlock* tmp = m_useBlockList.front();
		if (tmp)
		{
			delete tmp;
		}
		m_useBlockList.pop_front();
	}
	m_useBlockList.clear();

	while (!m_freeBlockList.empty())
	{
		CBlock* tmp = m_freeBlockList.front();
		if (tmp)
		{
			delete tmp;
		}
		m_freeBlockList.pop_front();
	}
	m_freeBlockList.clear();
}

CBlockBuffer::~CBlockBuffer()
{
	destroy();
}

CBlock* CBlockBuffer::allocBlock()
{
	if (m_freeBlockList.empty())
	{
		return CBlock::create();
	}
	else
	{
		CBlock* tmp = m_freeBlockList.front();
		m_freeBlockList.pop_front();
		m_freeBlockList.clear();
		return tmp;
	}
}

int  CBlockBuffer::write(char* buffer, int totalSize)
{
	int lastSize = totalSize;
	//寫入到最後一個block
	if (!m_useBlockList.empty())
	{
		CBlock* tmp = m_useBlockList.back();
		if (tmp)
		{
			int writeSize = tmp->write(buffer, lastSize);
			tmp->setTailOffset(writeSize);
			lastSize -= writeSize;
			buffer += writeSize;
		}
	}

	//沒寫完就申請一個block繼續寫入
	while (lastSize > 0)
	{
		CBlock* tmp = allocBlock();
		if (tmp )
		{
			int writeSize = tmp->write(buffer, lastSize);
			tmp->setTailOffset(writeSize);
			lastSize -= writeSize;
			buffer += writeSize;
			m_useBlockList.push_back(tmp);
		}
		else
		{
			break;
		}
	}
	m_useSize += (totalSize - lastSize);
	return totalSize - lastSize;
}

int  CBlockBuffer::readNotMove(char* buffer, int totalSize)
{
	int lastSize = totalSize;
	while (lastSize > 0)
	{
		if (m_useBlockList.empty())
		{
			break;
		}
		CBlock* tmp = m_useBlockList.front();
		if (tmp)
		{
			int readSize = tmp->read(buffer, lastSize);
			lastSize -= readSize;
			buffer += readSize;
			if (tmp->empty())
			{
				tmp->clear();
				m_useBlockList.pop_front();
				m_freeBlockList.push_back(tmp);
			}
		}
	}
	return totalSize - lastSize;
}

int  CBlockBuffer::read(char* buffer, int totalSize)
{
	int lastSize = totalSize;
	while (lastSize > 0)
	{
		if (m_useBlockList.empty())
		{
			break;
		}
		CBlock* tmp = m_useBlockList.front();
		if (tmp)
		{
			int readSize = tmp->read(buffer, lastSize);
			tmp->setHeadOffset(readSize);
			lastSize -= readSize;
			buffer += readSize;
			if (tmp->empty())
			{
				tmp->clear();
				m_useBlockList.pop_front();
				m_freeBlockList.push_back(tmp);
			}
		}
	}
	m_useSize -= (totalSize - lastSize);
	return totalSize - lastSize;
}

void CBlockBuffer::reset()
{
	while (!m_useBlockList.empty())
	{
		CBlock* tmp = m_useBlockList.front();
		if (tmp)
		{
			tmp->clear();
			m_freeBlockList.push_back(tmp);
		}
		m_useBlockList.pop_front();
	}
	m_useBlockList.clear();
	m_useSize = 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章