Espressif's embedded development libraries for the ESP32 microcontroller contain an event system based on FreeRTOS.

The event system handles connectivity, interrupts and other IO activity, but it's also extensible by the user. It's the latter part I'm interested in.

How is this extensible architectural pattern named?

How is this extendible event management architectural pattern named, in which the set of events can be extended, incorporated into my own API, and handled by the existing event loop (and its thread/task handling, integration, etc.)?

More details

With the current architectural design of that library, I can for example declare a new "class" of events and use them as part of my own code's APIs. In other code I can register event handlers and asynchronously receive these events, along with a payload of relevant data. My own code can then post events eg. on state changes, interrupts, or IO activity.

It is extremely simple in its interface eg. to declare a set of events for users of my library to listen for:


typedef enum {
} mylib_event_t;

To listen for events:


To post events:

  args, size_of_args,
  /* maybe timeout, priority, etc. */

The most useful thing for me by far is being able to extend the set of events, incorporate them into my own API, and let the existing event loop (and its thread/task handling, integration, etc.) handle it all. I'm not as concerned with the IO side of things, what I really want the events for is interaction between libraries within a single process.

Why I need the terminology?

Espressif's library is written for the ESP32 using FreeRTOS. I would like to have a similar library for POSIX systems (still in C). I could roll my own with threads and synchronisation primitives, but using an established library is always preferable.

The problem is, I don't know what that is typically called, so I have no idea what to look for:

  • Searching for "event loop" or "event library" brings me to eg. libevent, libev, libuv. These do the event-based IO side of things, but aren't designed to be extended.

  • Searching for "library" + any of: "message passing", "message queue", "publish subscriber or "pubsub" etc. brings me to eg. zeromq, nng (ex. nanomsg). Again, these handle the IO but aren't easy to extend. Where message serialisation APIs are provided they is nowhere near as simple and transparent as the above.

Knowing the commonly accepted name of that kind of architecture would help me finding existing libraries, or advices to develop my own.

  • Not sure why there's a close vote for "opinion based." There are many, many named patterns and architectures in software engineering, and if the thing I describe does not have a common name, that is also not an opinion.
    – detly
    Commented Aug 6, 2020 at 6:57
  • 1
    It is also (quite specifically) not a request for a recommendation. Could those voting to close please provide some specifics? If terminology questions are off-topic here, is there a Stackexchange site where they are not?
    – detly
    Commented Aug 6, 2020 at 7:05
  • 1
    I dared to slightly edit your question in order to make clear that you are not asking for resources but asking for terminology corresponding to a specific design, and why this terminology matters. Hope this helps.
    – Christophe
    Commented Aug 6, 2020 at 9:51
  • @Christophe Thank you! I agree, it's much clearer.
    – detly
    Commented Aug 6, 2020 at 9:56
  • 1
    You explicitly ask how this pattern is named - but a pattern is just a name, and you're presuming that this is a well-known named pattern. I don't think that a generic (typed) message queue + a registry of handlers is sufficiently special and exotic to need its own Proper Noun Pattern Name - it's just a message queue, a mapping from message type to handler(s?), and simple event loop. You haven't shown the argument serialization or the handler interface, so I can't tell if that's doing something special.
    – Useless
    Commented Aug 6, 2020 at 10:36

1 Answer 1


but aren't designed to be extended.

I'm not quite sure how much you researched the event libraries you mentioned, but they do support creating custom events. For example, with libevent, when creating an event structure, you can pass in -1 to the file descriptor to create an event that can only be triggered manually and not by IO:

If events contains one of EV_READ, EV_WRITE, or EV_READ|EV_WRITE, then fd is a file descriptor or socket that should get monitored .... If events contains EV_SIGNAL, then fd is a signal number to wait for. If events contains none of those flags, then the event can be triggered only by a timeout or by manual activation with event_active(): In this case, fd must be -1. (doc: event_new)

It's quite trivial to write a wrapper that hides the bits you don't care about if you only use custom events in your application and never need IO triggered events. libevent internally also have some convenience wrappers that makes some common tasks easier like event_base_once() if all your tasks are one-offs, so you can treat the event system more like a queue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.