Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

C++ Multicast Events

4.67/5 (7 votes)
8 Jan 2014CPOL2 min read 14.4K   249  
Helpers to declare and define multicast event sources and sinks in C++

Introduction 

Many programming languages natively offers some kind of event handling inclusive or delegates. There are many great solutions out on the web like Member Function Pointers and the Fastest Possible C++ Delegates [^] which is still one of my most favourite codeproject articles, or Boost [^] and Loki [^] which are the first libraries which come into my mind.

The provided source code offers a basic solution to declare and define multicast event sources and event sinks in C++.

Background

The provided solution heavily uses macros to

  • define templated base classes which can be used to declare and define event sources;
  • define base classes which can be used to declare and define event sinks.

One of the few positive points of approaching the problem using macros and inheritance is that easy readable method names can be generated for the event getters.

All negative aspects of macros on the other side, especially fancy ones, are well known. The new C++ language features also offers plenty of opportunities for new approaches.

The solution also doesn't provide means to specify return types in signatures. It could be added easily, but I think this would need additional treatment to be really consistent as I tried to show in this C# tip [^], so it might be part of a follow up. 

Using the code 

The attached source contains the header file MulticastEvent.h which is the only one needed to included to use the library.  

C++
#include "MultiCastEvent.h" 

Event signatures then can be defined like this:  

C++
#define MULTICAST_EVENT_CALLED_A (ClassExposingEvents, MethodACalledEvent, int, x, int, y)
#define MULTICAST_EVENT_CALLED_B (ClassExposingEvents, MethodBCalledEvent)

Event sources then can be defined using the event signatures like this: 

C++
// a class which exposes two events named MethodACalledEvent and MethodBCalledEvent
class ClassExposingEvents
{
public:
    ClassExposingEvents() 
        // initialize the multicast target lists
        : MULTICAST_EVENT_VAR_DEF(MULTICAST_EVENT_CALLED_A)
        , MULTICAST_EVENT_VAR_DEF(MULTICAST_EVENT_CALLED_B)
    {};
    ~ClassExposingEvents() {};
public:
    // declare and define the two events
    DECLARE_MULTICAST_EVENT(MULTICAST_EVENT_CALLED_A);
    DECLARE_MULTICAST_EVENT(MULTICAST_EVENT_CALLED_B);
public:
    // two example methods which invoke the events and report themselfes
    void a(int x, int y) { getMethodACalledEvent().invoke(x, y); /* 2do: add code */ };
    bool b() { getMethodBCalledEvent().invoke(); /* 2do: add code */ return true; };
};

And event sinks can be defined similarly: 

C++
// a class which sinks the two exposed events of ClassExposingEvents to report on invocation
class ClassImplementingEventHandlers 
    // implement the interfaces of the events
    : public DECLARE_MULTICAST_EVENT_TARGET_SUPERCLASS(MULTICAST_EVENT_CALLED_A)
    , public DECLARE_MULTICAST_EVENT_TARGET_SUPERCLASS(MULTICAST_EVENT_CALLED_B)
{
public:
    ClassImplementingEventHandlers() {};
    ~ClassImplementingEventHandlers() {};

public:
    // declare or inline define the event handlers to report when being invoked
    DECLARE_MULTICAST_EVENT_TARGET(MULTICAST_EVENT_CALLED_A) /* or define it inline */;
    DECLARE_MULTICAST_EVENT_TARGET(MULTICAST_EVENT_CALLED_B) /* or define it inline */; 
};

// define the event handlers if they haven't got inline defined to report when being invoked
DEFINE_MULTICAST_EVENT_TARGET(ClassImplementingEventHandlers, MULTICAST_EVENT_CALLED_A)
{
    // todo: add handler code
}

DEFINE_MULTICAST_EVENT_TARGET(ClassImplementingEventHandlers, MULTICAST_EVENT_CALLED_B)
{
    // todo: add handler code
}

After instantiating, sources and sinks can be routed like shown here: 

C++
// define event sources
ClassExposingEvents eventSource;

// define event sinks
ClassImplementingEventHandlers eventSink;

// create routes
eventSource.getMethodACalledEvent().addListener(eventSink); 

Points of Interest 

The provided source code is very basic and does only provide the bare minimum to serve as a starting point for further development.  Neither thread safety, nor performance, memory usage or other aspects are covered.

History 

  • 2014/01/08: First version submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)