2011-03-24 69 views
0

我正在處理事件的遊戲引擎組件。我想要做的是創建一個系統,我可以通過名稱註冊新的事件類型。然後,事件管理器將持有一系列事件類型和工廠來生成這樣的事件類型,但是我想讓它使用一個池化系統,以便創建一個事件,然後使用它,然後而不是刪除它,把它列入一個列表。下一次我創建該事件,而不是使用堆,我可以從池中分配。模板抽象工廠類與池

SO特定事件類型的這些層次...

struct TEvent 
{ 
    int nID; 
    int nTimeStamp; 
}; 

struct TCollisionEvent : public TEvent 
{ 
    TEntity* pEntity1; 
    TEntity* pEntity2; 
    Vector3* pvecPoint; 
}; 

然後我創建了一個智能工廠,這是否創建/循環的競爭操作:

template <class BASE_CLASS> 
class CSmartFactory 
{ 
private: 
    typedef typename std::list<BASE_CLASS*> TBaseList; 
    typedef typename std::list<BASE_CLASS*>::iterator TBaseListItr; 

    TBaseList* m_plstPool; 

public: 
    explicit CSmartFactory() 
    { 
    m_plstPool = NULL; 
    } 

    ~CSmartFactory() 
    { 
    TBaseListItr itr; 

    if (m_plstPool) 
    { 
     for (itr = m_plstPool->begin(); itr != m_plstPool->end(); itr++) 
     { 
     BASE_CLASS* pEntity = *itr; 
     SAFE_DELETE(pEntity); 
     } 

     m_plstPool->clear(); 
     SAFE_DELETE(m_plstPool); 
    }  
    } 

    bool Init(int nPoolSize) 
    { 
    bool bReturn = false; 

    do 
    { 
     m_plstPool = new TBaseList; 
     IwAssert(MAIN, m_plstPool); 

     while (nPoolSize--) 
     { 
     BASE_CLASS* pBaseObject = new BASE_CLASS; 
     IwAssert(MAIN, pBaseObject); 

     m_plstPool->push_back(pBaseObject); 
     } 

     bReturn = true; 
    } while(0); 

    return bReturn; 
    } 

    BASE_CLASS* Create() 
    { 
    BASE_CLASS* pBaseObject = NULL; 

    // 
    // grab a pre-made entity from the pool or allocate a new one 
    if (m_plstPool->size() > 0) 
    { 
     pBaseObject = m_plstPool->front(); 
     m_plstPool->pop_front(); 
     pBaseObject->Clear(); 
    } 
    else 
    { 
     pBaseObject = new BASE_CLASS; 
     IwAssert(MAIN, pBaseObject); 
    } 

    return pBaseObject; 
    } 

    void Recycle(BASE_CLASS* pBaseObject) 
    { 
    m_plstPool->push_back(pBaseObject); 
    } 
}; 

所以,現在我可以這樣做:

CSmartFactory<TCollisionEvent>* pCollisionEventFactory = new CSmartFactory<TCollisionEvent>; 

但是我想要做的是讓我的事件管理器允許動態事件註冊bu這就是我陷入困境的地方。

理想情況下,RegisterEvent會追蹤stl :: map或其他東西的名稱和工廠指針,但不太清楚如何到達那一點。也許我完全走錯了路。

這將編譯

class TEventManager 
{ 
public: 
    TEventManager(); 
    ~TEventManager(); 

    bool RegisterEvent(char* pszEventName, CSmartFactory<TEvent>* pFactory); 
}; 

在您添加

TEventManager::RegisterEvent("CollisionEvent", new CSmartFactory<TEntityCollisionEvent>); 

所以現在我絕望地試圖找到一種方法,使這一切工作。

有人在這裏有一些想法!?

Fred

回答

0

我假設你想重用事件來避免昂貴的堆malloc/free的?

我認爲這裏的正確答案不是通過編寫自己的結構來重用對象來卷積代碼,而是使用小對象分配器。作爲開始,可能需要查看boost::pool

+0

正確,我非常想避免昂貴的malloc/free的。 唯一的問題是,我正在使用的這個特定平臺不支持增強,因此我試圖把我自己放在一起。 我覺得我走在正確的道路上! – Fred 2011-03-24 02:05:33

+0

我可以問......你的特定平臺是什麼? – 2011-03-24 02:10:00

+0

使用AirPlay SDK,因此它是一個受限制的系統,並且他們沒有提升的官方支持,儘管有些人在各種部分被黑客入侵。 – Fred 2011-03-24 02:12:52

0

這兩個類CSmartFactory<TEntityCollisionEvent>CSmartFactory<TEvent>將產生類似

  • CSmartFactory_TEntityCollisionEvent

  • CSmartFactory_TEvent

他們實際上是兩個獨立的和無關的類。試圖交替使用它們將是不明智的,儘管它們表現相同(它們的類型是多態的)。

動態鑄造不會工作,你可以嘗試但用蠻力鑄造:

TEventManager::RegisterEvent("CollisionEvent", 
     reinterpret_cast<CSmartFactory<TEvent>*>(new CSmartFactory<TEntityCollisionEvent>)); 

警告:在您自己的風險!;-)

0

好吧,經過很多頭撞擊後,我意識到解決方案比我試圖拉開的更簡單。

所有經理應該關心的是管理一個TEvent *。每個TEvent都有一個唯一的哈希值,使其具有唯一性,因此當添加新事件時,該字符串的名稱和哈希名稱都會被存儲。所以從那裏我可以添加一個指向任何子類的指針,只要它被轉換爲TEvent。

我讓它遠比它所需要的更復雜。