Sponsored Link •
|
Summary
I show how static event handlers through template function specializations can be simpler and more efficient than dynamic event handlers through function pointers.
Advertisement
|
Often in event driven frameworks, functions pointers are used, to allow the user of a library to respond to particular events generated by a library. If we know the event handlers to be static (i.e. not changing during program execution) then we can use another simpler and more efficient technique based on template function specializations. This post is intended to replace the somewhat inelegant previous post I made. on the technique.
I have also demonstrated the technique in action in a minimal Win32 GUI application at http://www.codeproject.com/useritems/winevent.asp
Here is a C++ program which shows the two techniques side by side:
#include <stdio.h> #include <time.h> const int BIG_NUM = 100000000; const int EVENT_A = 0; const int EVENT_B = 1; int gnCnt = 0; ///////////////////////////////////////////////// // static dispatch code template<typename int> inline bool StaticHandler(int nArg) { return false; } template<typename Dummy_T> void StaticDispatch() { while (StaticHandler<EVENT_A>(BIG_NUM)) { StaticHandler<EVENT_B>(1); } } ///////////////////////////////////////////////// // dynamic dispatch code typedef bool (*HandlerFxn)(int); bool DefaultDynamicHandler(int nArg) { return false; } HandlerFxn FxnPtrTable[2] = { &DefaultDynamicHandler, &DefaultDynamicHandler }; void RegisterHandler(int EventCode, HandlerFxn pFxn) { FxnPtrTable[EventCode] = pFxn; } void DynamicDispatch() { while (FxnPtrTable[EVENT_A](BIG_NUM)) { FxnPtrTable[EVENT_B](1); } } ///////////////////////////////////////////////// // dynamic user-defined event handlers inline bool DynamicHandlerA(int nArg) { return gnCnt < nArg; } inline bool DynamicHandlerB(int nArg) { gnCnt += nArg; return true; } ///////////////////////////////////////////////// // static user-defined event handlers template<> inline bool StaticHandler<EVENT_A>(int nArg) { return gnCnt < nArg; } template<> inline bool StaticHandler<EVENT_B>(int nArg) { gnCnt += nArg; return true; } ///////////////////////////////////////////////// // main entry point int main() { int nStart; int nEnd; { gnCnt = 0; RegisterHandler(EVENT_A, &DynamicHandlerA); RegisterHandler(EVENT_B, &DynamicHandlerB); nStart = clock(); DynamicDispatch(); nEnd = clock(); printf("time elapsed for dynamic dispatch %d msec\n", (nEnd - nStart) * CLOCKS_PER_SEC / 1000); } { gnCnt = 0; nStart = clock(); StaticDispatch<void>(); nEnd = clock(); printf("time elapsed for static dispatch %d msec\n", (nEnd - nStart) * CLOCKS_PER_SEC / 1000); } getchar(); return 0; }
On my system (Windows XP) and compiler (Visual C++ 7.1) I got results of roughly 2000 msec for dynamic dispatch versus 1500 msec for static dispatch. This is not surprising considering that the compiler can much more easily optimize the template calls. Compilers are not good at guessing when dynamic contexts are in fact static. This is what programmers are for.
Notice that the static dispatch system requires far less code and does not need any kind of registration step.
Have an opinion? Readers have already posted 4 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Christopher Diggins adds a new entry to his weblog, subscribe to his RSS feed.
Christopher Diggins is a software developer and freelance writer. Christopher loves programming, but is eternally frustrated by the shortcomings of modern programming languages. As would any reasonable person in his shoes, he decided to quit his day job to write his own ( www.heron-language.com ). Christopher is the co-author of the C++ Cookbook from O'Reilly. Christopher can be reached through his home page at www.cdiggins.com. |
Sponsored Links
|