3
\$\begingroup\$

I've finally implemented an extendable message class and messageServer class. The message class dynamically assigns a unique static ID to each derived message type (ex. ObjectCreatedMessage might be assigned id = 1). The actual message data is a member of the derived class.

Messages can be pushed to MessageServer class by upcasting to MessageBase*.

Systems (or anything) can subscribe to Message Server by passing a std::function to:

typedef std::function<void(MessageBase*)> Callback;
void registerCallback(int messageType, Callback callback);    

When MessageServer is processing messages, it pops a message off the queue, checks the message type, then sends the message to each callback function registered to that type.


My Questions are:

  1. Is this efficient?
  2. How could I implement an "unregister" function? std::functions can't be compared by equality.
  3. What is a smart way to handle the callback failing? (perhaps the registered object went out of scope so the function pointer is undefined)
\$\endgroup\$
3
  • \$\begingroup\$ You could wrap the std::function in another class that is derived from an ICallback base and have each derived type support a typeid retrieval system (as you did for the messages). Then you could use that thing to compare ICallback references/pointers more reliably. Or, if you're not talking about types, having a lock protected id generator static variable in the ICallback can help you manage unique, derived callback instances (not just by types). Would this be ok for you? (polymorphism isn't fast, but if you're not bothered by its minor performance hit, it's good enough) \$\endgroup\$
    – teodron
    Commented Aug 29, 2013 at 15:16
  • \$\begingroup\$ PS: you have more chances getting a response on stackoverflow - it's a general programming/c++ question and the c++ world is bigger on SO. \$\endgroup\$
    – teodron
    Commented Aug 29, 2013 at 15:21
  • \$\begingroup\$ @teodron thanks for the info... i'll look into that. What I did for now is have the registration function return a unique key that must be passed to unregister. This would be much better encapsulated in a Callback base class. \$\endgroup\$
    – Bryan
    Commented Aug 30, 2013 at 3:55

1 Answer 1

1
\$\begingroup\$

Using callbacks can be one way to decouple parts of a program. They're often used in GUI interaction because this interaction is generally sporadic and not something that happens excessively. So the caveats and downsides to callbacks don't out weigh the benefits of them.

If you intend to use callbacks for event handling, be mindful that emitting function callbacks in tight loops could be detrimental to your instruction and data cache.

Lastly, don't over estimate the power of polling. Often it is far more efficient to have an event be raised and placed into a queue/buffer. At future points in your code, you poll to determine what events have been raised that are of interest. This approach may be easier to apply parallel processing constructs against than if you used an immediate callback concept.

\$\endgroup\$
1
  • \$\begingroup\$ I ended up going the polling route, with an option for callbacks instead (for certain messages that should have immediate response). Also I created a Cookie class that holds a function option to unregister... that way when the subscribed object goes out of scope, the Cookie class unregisters on destruction. \$\endgroup\$
    – Bryan
    Commented Sep 13, 2013 at 8:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .