The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Best method of implementing callbacks

I'm designing an API.  I want to be able to launch callbacks.  I'm either going to derive from a callback class or use boost Function to implement functional callbacks.

struct Callback {
  virtual void run();
  virtual ~Callback() {}
void regCallback(Callback cb);

typedef boost::function<void ()> Callback;
void regCallback(Callback cb);

The boost Function method is more flexable.  But the polymorphic class allows for easier expansion.  If there are multiple callbacks based on a condition or I need to get data out from the callback.

Is there any reason to favor one over the other?

Wednesday, June 27, 2007
If you want to do a COM wrapper for your API (to support  languages other than C++) in the future, then the first method would be better (more portable).

I've been working on a cross platform market data delivery API where we used the first method, and it worked for many languages (C++, C#, VB, Delphi) well. But we did it a bit another way:

class Callback
    virtual void run()
      int a = 2 + 2;
      // do something and call userFunc

    virtual ~Callback() {};
    virtual void userFunc(int x) {};

class MyClass: public Callback
  virtual void userFunc(int x)
    // use x here

This also works well if you need to have several types of different callback functions (e.g. userFunc1, userFunc2 etc.) so you don't need to call regCallback for each of them.
Wednesday, June 27, 2007
If you go with the polymorphic class, sometimes people get into trouble by destroying a callback class instance while a callback is happening.
Christopher Wells Send private email
Wednesday, June 27, 2007
Do not ask what is better for you, ask what is easier for your clients.
What is the easiest approach for code using your API to register and receive a callback?

Marc Jacobi Send private email
Wednesday, June 27, 2007
Observer pattern
Dino Send private email
Wednesday, June 27, 2007
How about: Plain C pointer-to-functions using stdcall calling convention?

These can be handled from .NET, Delphi (I think) C, and C++.

PS - Forget COM.
Meganonymous Rex Send private email
Wednesday, June 27, 2007
Is the application single or multithreaded? Call backs in multithreaded applications can tricky because the call back might happend from one thread to a function been used by another thread or even more than one call-back might be rised at the same time.

If this is the case, use an Reactor-acceptor pattern to serialize the dispatch the call-backs.
Pablo Chacin Send private email
Thursday, June 28, 2007
I appreciate the input.  This is implementing the Observer pattern.  I'm not so worried about how they are called, so the reactor pattern isn't a major concern.

C function pointers are out because we need to be able to pass in object member functions.  We also have no need to worry about additional languages.

I would like to limit the requirements on the users of my API.  This seems to lead me to taking boost::function.  But I'm also worried that I may need a group of related callbacks.

I could have the user pass in each callback of the group individually, create a container class (named record) with all of them, or use a callback class to define all of the needed callback functions.

I think I've decided to go with the flexibility of boost:function.  Thanks for your input.

Thursday, June 28, 2007
C function points can easily work with an extra void* parameter. Then you can easily generate a callback function a member function or to a non-member function.

Even with the other libraries, you're going to need someway to specify the instance of the member function you want to use.

Friday, June 29, 2007
Have a look at Don Clugston's excellent FastDelegate code at CP: and Quynh Nguyen's "A new way to implement Delegate in C++"
Neville Franks Send private email
Sunday, July 01, 2007

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz