2011-03-24 89 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。

我让它远比它所需要的更复杂。