2012-05-22 119 views
2

如果我有這些聲明和定義:事件系統優化

enum Events 
{ 
    INIT, 
    RENDER 
}; 

struct EventBase 
{ 
    typedef void (EventBase::*event_callback_type)(); 

    ~EventBase() {} 

    virtual void init() { assert(0); } 
    virtual void render() { assert(0); } 
}; 

template <enum Events> 
struct EventTraits 
{ 
    static EventBase::event_callback_type const event_callback; 
}; 

// in a .cpp file 
template <> 
EventBase::event_callback_type const 
EventTraits<INIT>::event_callback(
    &EventBase::init); 

template <> 
EventBase::event_callback_type const 
EventTraits<RENDER>::event_callback(
    &EventBase::render); 

// in another class *i are pointers to objects that inherit EventBase 
template <enum Events event> 
inline void EventNotifier::notify() 
{ 
    for (events_type::const_iterator i(event_handlers[event].begin()); 
    i != event_handlers[event].begin() + num_event_handlers[event]; 
    ++i) 
    { 
    ((*i)->*EventTraits<event>::event_callback)(); 

    if ((*i)->num_event_handlers[event]) 
    { 
     (*i)->notify<event>(); 
    } 
    // else do nothing 
    } 
} 

說,該事件渲染需要儘可能快的處理,你認爲它是值得做的一員模板特:

template <> 
inline void EventNotifier::notify<RENDER>() 
{ 
    for (events_type::const_iterator i(event_handlers[RENDER].begin()); 
    i != event_handlers[RENDER].begin() + num_event_handlers[RENDER]; 
    ++i) 
    { 
    (*i)->render(); 

    if ((*i)->num_event_handlers[RENDER]) 
    { 
     (*i)->notify<RENDER>(); 
    } 
    // else do nothing 
    } 
} 

這不需要獲取靜態指針到成員函數。或者我應該這樣做:

template <enum Events> 
struct EventTraits 
{ 
    static EventBase::event_callback_type event_callback(); 
}; 

並專門化結構模板?

+0

什麼是你的目標體系?這很重要,因爲它會影響到加載命中停頓和分支預測時間等。一些編譯器具有配置文件指導的優化,如果啓用可能會讓您的速度提升。 –

+0

這是armv7,霓虹燈的擴展。 – user1095108

+1

要知道的唯一真正的方法就是嘗試一下:在程序運行時將它與您的編譯器和配置文件(時間)進行編譯。編譯器在它們內部做了奇怪而美妙的事情,因爲即使你自己的CPU也不會盲目地執行它所得到的指令,所以你經常認爲在邏輯上必須發生在你的代碼之下,而不是。 – thehouse

回答

2

只需額外5美分。 EventNotifier :: notify()看起來完全線程不安全。此外,如果任何事件處理程序生成新事件,則可能發生不良事件。我建議做通知這種方式(C++ 11,只是不知道你所有的類型):

template <> inline void EventNotifier::notify<RENDER>() 
{ 
    decltype(event_handlers[RENDER]) local; 
    decltype(num_event_handlers[RENDER]) local_num; 

    { 
    std::lock_guard<std::mutex> guard(my_mutex); 
    local = event_handlers[RENDER]; 
    local_num = num_event_handlers[RENDER]; 
    } 

    for (events_type::const_iterator i(local.begin()); i != local.begin() + local_num; ++i) 
    { 
    (*i)->render(); 

    if ((*i)->num_event_handlers[RENDER]) (*i)->notify<RENDER>(); 
    } 
} 
+1

我正在尋找速度和鎖定殺死它。事件處理程序只是將其稱爲「子」,以便傳播事件。說,你調用'應用程序 - >通知();'和所有的孩子將被通知呈現。 – user1095108

+0

那麼它更好地移除條件i!= event_handlers [RENDER] .begin()+ num_event_handlers [RENDER];從循環中檢查.end() –

+0

event_handlers [RENDER]是一個std ::數組,而不是std :: vector。速度是至關重要的。 – user1095108

1

成員專業化不會使任何區別在它的當前形式,你寫在相同的代碼編譯器將爲您生成的代碼。

這裏有一個小的改進:

template <enum Events event> 
inline void EventNotifier::notify() 
{ 
    for (events_type::const_iterator i(event_handlers[event].begin()), 
     end (event_handlers[event].begin() + num_event_handlers[event]); 
     i != end; ++i) 
    { 
    ((*i)->*EventTraits<event>::event_callback)(); 

    if ((*i)->num_event_handlers[event]) 
    { 
     (*i)->notify<event>(); 
    } 
    // else do nothing 
    } 
} 
+0

謝謝!你確定你說什麼嗎?在專業化我不是指一個靜態成員,它不需要被提取。 – user1095108

+0

啊沒有發現'(* i) - > render()'。回想起來,這是你問題的主要觀點。 –