去年的時候,就有想法寫一個屬於自己的遊戲服務器框架。所以今年春節假期花了很多時間去閱讀代碼。在萬分糾結下,最終選擇了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 動漫 記錄
文章來源: