【重拾CPP】關於對像池

分類:IT技術 時間:2017-02-04

      去年的時候,就有想法寫一個屬於自己的遊戲服務器框架。所以今年春節假期花了很多時間去閱讀代碼。在萬分糾結下,最終選擇了C++語言(差點就想用golang了)來實現。從今日起,會記錄些實現的細節。 如遇上大神,請指點一下。

       順帶提一下,我的服務器框架名字叫做Fairy(妖精)。靈感覺來自於一部動漫《妖精的尾巴》,其中的  梅比斯·維維亞米利歐 給自己的魔法公會定義為《妖精的尾巴》解釋到:“妖精到底有沒有尾巴呢...其實說到底連妖精是否存在都沒有人能確定 正因為如此這才是永遠的未知...永遠的冒險 這個名字正是包含著這種意思哦”。因為寫“Fairy Tail ”太長了,就把尾巴給去了,簡略成了Fairy。

      言歸正轉,在服務器中,有很多對像可以重復利用的,比如User,Buff,Conn等對像。我參考了一部分網上搜索出來的代碼,用完後,都是手動的回塞回去(例:http://www.wuzesheng.com/?p=674)。那麽,有沒有辦法,完全不用操心這事情呢?有,那就是利用std::share_ptr(如果你不是用的C++11,就簡單實現一個吧,不難的)。

以下是我的對像池申明:

template <typename T>
class ObjectPool;

我們需要將所有的對像,放入一個申明好的隊列裏。因為考慮到線程安全的問題,我封裝了一個基MutexQueue。

template<typename T>
class MutexQueue
{
public:
	~MutexQueue()
	{
		mMutex.lock();
		while (!mObjectQueue.empty())
		{
			mObjectQueue.pop();
		}
		mMutex.unlock();
	};

	T pop()
	{	
		mMutex.lock();
		if (mObjectQueue.empty())
		{
			mMutex.unlock();
			return nullptr;
		}
		auto obj = mObjectQueue.front();
		mObjectQueue.pop();
		mMutex.unlock();
		return obj;
	};

	void push(T obj) 
	{
		mMutex.lock();
		mObjectQueue.push(obj);
		mMutex.unlock();
	};
private:
	std::mutex mMutex;
	std::queue<T> mObjectQueue;
};

對像池隊列申明: 

MutexQueue<std::shared_ptr<T>>* mObjectQueue;

封裝一個創建對像的方法,註意這裏是關健,std::share_ptr默認的deleter器是delete,如果我們將這個deleter寫成重新塞回隊列,那麽就不用自己去操作,把這個對像重新回收了。但要註意的是,當線程池函數析構的時候,也需要析構掉隊列裏的數據。

std::shared_ptr<T> makeSharePtr(T* obj)
	{
		std::shared_ptr<T> objTmp = std::shared_ptr<T>(obj, [this](T* ptr) {
			if (mIsRelase)
			{
				this->releaseObject(ptr);
			}
			else
			{
				this->recoverObject(ptr);				
			}
		});

		return objTmp;
	};

以下是相應的回收函數及析構函數,取對像函數(我還沒有對線程池做數量上的限制,我在考慮有沒有必要)

/*獲取操作對像*/
	std::shared_ptr<T> acquireObject()
	{
	
		std::shared_ptr<T>	obj =	mObjectQueue->pop();
		if (obj.get() == nullptr)
		{
			T* objPtr = new T();
			obj = makeSharePtr(objPtr);
		}

		return obj;
	};

	//回收對像
	void recoverObject(T* objPtr)
	{
		mObjectQueue->push(makeSharePtr(objPtr));
	};

	//釋放內存
	void releaseObject(T* objPtr)
	{
		if (objPtr != nullptr)
		{
			delete objPtr;
			objPtr = nullptr;
		}
	};

最後,為了能夠正常析構掉對像對隊列裏的數據,MutexQueue是手動創建的:

	ObjectPool(int chunkSize = 0)
	{
		mIsRelase = false;
		mObjectQueue = new MutexQueue<std::shared_ptr<T>>();
	};

	~ObjectPool()
	{
		mIsRelase = true;
		delete mObjectQueue;
	};

^_^完,閱讀愉快。


Tags: 遊戲服務器 妖精的尾巴 public 動漫 記錄

文章來源:


ads
ads

相關文章
ads

相關文章

ad