一种资源池的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wenzhou1219/article/details/84640138

这两天看到一种静态链表的实现,刚好可以拿来做资源池的实现,记下供参考。

先说静态链表,这最开始为了给Pascal等没有指针的语言来实现链表的一种方式,为了模拟链表指针指向下一个节点的方式,静态聊表使用数组下标来表示下一个元素的位置

就算是在有指针的语言中,使用静态链表也有它的优势:初始化后相对顺序存储结构插入删除元素不需要移动元素,相对指针实现的链表不需要动态分配和删除元素内存,正好适用于固定大小的资源分配池的实现。

思路

如下初始化一个数组作为静态链表,每个元素初始指向第后一个元素,初始size=0,头结点head指向第1个节点,下一个可分配节点也指向第1个节点。

接下来,如下连续分配4个节点,则size=4,head按照头插入生成链,因此head指向第4个节点,分配的节点依次指向之前分配的节点,next指向第5个节点。

接下来,如下先后删除第4和第1个分配的节点,则size=2,此时head指向第3个元素,next下一个可分配的则是最后删除的第1个节点。可以看到,其实相当于有两条链存在这个数组中,已分配的head链和待分配的next链互补,申请元素时将next链元素给head链,删除元素时head链将元素还给next链。这样的方式非常适合做资源池的实现。

具体实现

抽象元素类型T和初始大小nInitSize,以一个数组作为静态表分配,模板类声明如下

template <class T, uint32_t nInitSize>
class StaticLinkList
{
private:
	...

	typedef struct
	{
		T data;
		uint32_t next;
	}ElemType;
	ElemType m_dataArr[nInitSize];

	uint32_t m_nIndexHead;
	uint32_t m_nIndexNext;
	uint32_t m_nCurSize;
	...

初始化大小,head和next链

template <class T, uint32_t nInitSize>
void StaticLinkList<T, nInitSize>::Clear()
{
	memset(&this->m_dataArr, 0, sizeof(m_dataArr));
	for (int i = 0; i < nInitSize - 1; i++)
	{
		m_dataArr[i].next = i + 1;
	}

	m_nIndexHead = m_nIndexNext = m_nCurSize = 0;
}

封装静态链表元素分配和释放,其实就是从next链删除和增加

template <class T, uint32_t nInitSize>
uint32_t StaticLinkList<T, nInitSize>::Malloc_SL()
{
	uint32_t i = m_nIndexNext;
	m_nIndexNext = m_dataArr[i].next;
	return i;
}

template <class T, uint32_t nInitSize>
void StaticLinkList<T, nInitSize>::Free_SL(const int32_t nIndex)
{
	m_dataArr[nIndex].next = m_nIndexNext;
	m_nIndexNext = nIndex;
}

获取资源实现如下,只需要从next获取一个资源,添加到head链即可

template <class T, uint32_t nInitSize>
T* StaticLinkList<T, nInitSize>::Get()
{
	if (m_nCurSize >= nInitSize)
	{
		return NULL;
	}

	uint32_t nNewIndex = Malloc_SL();
	if (m_nCurSize != 0)
	{
		m_dataArr[nNewIndex].next = m_nIndexHead;
	}
	m_nIndexHead = nNewIndex;

	m_nCurSize += 1;
	return &m_dataArr[nNewIndex].data;
}

释放资源,只需要找到对应的元素,从head链删除,还给next链即可,这里还可以做下优化,每个分配的元素自己保存父节点,这样就可以直接找到自己的下标,快速删除

template <class T, uint32_t nInitSize>
bool StaticLinkList<T, nInitSize>::Delete(T *pdata)
{
	if (m_nCurSize<=0 || !pdata)
	{
		return false;
	}

	uint32_t nIndexFind = 0;

	if (&m_dataArr[m_nIndexHead].data == pdata)
	{
		nIndexFind = m_nIndexHead;
		m_nIndexHead = m_dataArr[m_nIndexHead].next;
	}
	else
	{
		bool bFind = false;
		uint32_t np = m_nIndexHead;
		for (uint32_t i=0; i < m_nCurSize - 1; i++)
		{
			if (&m_dataArr[m_dataArr[np].next].data == pdata)
			{
				bFind = true;
				break;
			}

			np = m_dataArr[np].next;
		}

		if (!bFind)
		{
			return false;
		}

		nIndexFind = m_dataArr[np].next;
		m_dataArr[np].next = m_dataArr[nIndexFind].next;
	}
	
	Free_SL(nIndexFind);
	m_nCurSize -= 1;
	return true;
}

如下分配一个简单的资源池,添加删除后再添加

	StaticLinkList<int, 10> l;

	int *p0= l.Get();
	int *p1 = l.Get();
	int *p2 = l.Get();
	int *p3 = l.Get();

	*p0 = 10;
	*p1 = 11;
	*p2 = 12;
	*p3 = 13;

	cout << "Init data:" << endl;
	l.Dump([](const uint32_t n, const int *a) { 
		cout << n << "->" << *a << endl; 
	});

	l.Delete(p3);
	l.Delete(p0);

	cout << endl << "Delete data:" << endl;
	l.Dump([](const uint32_t n, const int *a) {
		cout << n << "->" << *a << endl;
	});

	*l.Get() = 15;
	*l.Get() = 19;
	*l.Get() = 21;

	cout << endl << "After data:" << endl;
	l.Dump([](const uint32_t n, const int *a) {
		cout << n << "->" << *a << endl;
	});

运行结果为

Init data:
Head Index:3 Next Index:4 Cur Size:4
3->13
2->12
1->11
0->10

Delete data:
Head Index:2 Next Index:0 Cur Size:2
2->12
1->11

After data:
Head Index:4 Next Index:5 Cur Size:5
4->21
3->19
0->15
2->12
1->11

演示代码下载链接

原创,转载请注明来自http://blog.csdn.net/wenzhou1219 

猜你喜欢

转载自blog.csdn.net/wenzhou1219/article/details/84640138
今日推荐