views:

96

answers:

4

Hello all,

This is a question about generic c++ event driven applications design.
Lets assume that we have two threads, a "Dispatcher" (or "Engine"...) and a "Listener" (or "Client"...).
Let's assume that I write the Dispatcher code, and release it as a library. I also write the Listener interface, of course.
When the Dispatcher executes (after Listener registration)

listenerInstance.onSomeEvent();

the event handling code will actually be executed by the Dispatcher thread, so if the person that implements the Listener writes something like

void Listener::onSomeEvent() { while(true) ; }

The Dispatcher will stuck forever.

Is there a "plain old c++" (I mean no boost or libsigc++) way to "decouple" the two classes, so I can be sure that my Dispatcher will work fine whatever the Listeners does in the callbacks?

bye and thanks in advance,
Andrea

+2  A: 

One approach could be to call the onSomeEvent into a dedicated thread. This is not 100% bullet proof but it would avoid the while(true); issue.

I hope it helps

luc
+3  A: 

I'm afraid there's no native C++ way to do this. For windows, you can use asynchronous procedure calls (APC)

Seb
+4  A: 

Well if the event gets invoked in the same thread (as I seem to understand can be a requirement), then there isn't much you can do about it.

If this is under a Win32 app with a message pump, you could register a windows message and call PostMessage with data representing this event and you can patch the message loop to interpret that message and call the event. What you gain is a decoupling of sorts, the event call is asynchronous (ie the event call will return no matter what). But later on when you process your messages and actually call the event, your main thread will still be stalled and nothing else will run until the event handler is ready.

Another alternative is just creating a new thread (or using a thread pool) for your call. This won't work for events that require a certain thread (ie ui updating threads). Additionally this adds synchronization overhead and thread spawning overhead AND you might starve the system of threads and/or cpu time.

But really, I don't think it's your job as the library designer to anticipate and avoid these problems. If the end-user wants to create a long event handler, let him spawn a new thread on his own. If he doesn't and just wants his specific thread to handle an event, let him. It simplifies your job and doesn't add any overhead that's not needed.

Blindy
Hi, I agree with the fact that it might not be your job to prevent a bad use of your library.
Seb
+1  A: 

There is a pure C++ way to achieve what you're mentioning. However, it's very ineffective. Here's a sample:

class Listener
{
  bool myHasEvent;

private:
  void ProcessEvent()
  {
    while (true)
    {
      if (!myHasEvent)
        continue;           //spin lock

      // Do real processing
      myHasEvent = false;
    }
  }

public:
  void onSomeEvent() { myHasEvent = true; }
};

However, I would recommend against this approach. Instead, I would transform this into more platform-specific code. I would replace the if (!myHasEvent) continue; spin lock with a OS-specific wait routine (i.e. WaitForSingleObject on Win32) passing an Event Handle. Then, in onSomeEvent, instead of myHasEvent = true; I would set the event into signaled state (i.e. SetEvent on Win32). This would be a lot more effective because the thread wouldn't eat processor time during waiting.

Another method is the PostMessage as suggested by Blindly.

Kerido