4

Context

There is a modular C++ application. Each module provides an interface (an abstract class) which is used by other modules. There are no circular dependencies. The module interaction happens via direct method calls in one way, and via events (a variation of the observer pattern, similar to Qt's signals) in the other way.

For example:

// an interface towards the battery manager
class IBatteryManager
{
public:
    // get the battery level
    virtual int batteryLevel() = 0;
    // the system is about to run out of battery and enter
    // a power saving mode
    virtual Event<> &aboutToRunOutOfBattery() = 0;
};

The Event class looks like this:

template<typename... tArgs>
class Event
{
public:
    // client: the provided function will be called when this
    //         event is emitted
    void subscribe(std::function<void(tArgs...)>);
    // server: emit the event
    void notify(tArgs...);
};

Problem and Possible Solution

Sometimes a fire-and-forget event is not enough. A module might want to notify its clients about some event and wait until it is processed (and maybe get back some values).

For instance, BatteryManager might want to wait until all clients have processed the about-to-run-out-of-battery event before entering the power saving mode.

I can imagine multiple ways how this can be done. One of them would be to extend the Event class with the future/promise pattern in the following way:

template<typename tValue, typename... tArgs>
class Event
{
public:
    // client: now must return some value
    void subscribe(std::function<Future<tValue>(tArgs...)>);
    // server: this future is fulfilled as soon as all clients
    //         have completed their promises
    Future<std::vector<tValue>> notify(tArgs...);
};

Questions

Updated: I have rephrased questions a bit to be more clear.

Is there a design pattern which describes the approach shown above? In other words, does such approach have a commonly accepted name, vocabulary, pros/cons, a canonical implementation, a list of things one needs to pay attention to, and other stuff what patterns usually have?

I am asking because this might be not a problem which is unique to me. So I do not want to end up reinventing the wheel, both in terms of implementation (by probably re-doing someone else's mistakes) and terminology (by introducing my own terms, which will make the communication with other developers harder).

Secondary questions: Are there maybe better approaches? What would be the best practice in this case?

Kane
  • 179

1 Answers1

1

The point of the "Event" pattern is the source does not know or care if any listeners are attached. The source is decoupled from the clients. Events often are executed synchronously, but the source should not know about that either.

But in your case you want to wait for a return value, which means you are depending on the client and you are making assumptions about the behavior of the client (otherwise you wouldn't care if it had finished processing or not). So you have a straightforward dependency, which means the source should just go ahead and call the method directly - skip all the indirection with subscription and whatnot.

In short, what you are trying to do is not a recognized as a "pattern", since it is so simple: You want to call a method on another object.

JacquesB
  • 61,955
  • 21
  • 135
  • 189