C API
Core concepts
There are two central objects in the event ring C API. They are:
- struct
monad_event_ring
- represents an event ring whose shared memory segments have been mapped into the address space of the current process; the primary thing the client does with this object is use it to initialize iterators that point into the event ring, using themonad_event_ring_init_iterator
function - struct
monad_event_iterator
- the star of the show: this iterator object is used to read sequential events. The iterator'stry_next
operation copies the current event descriptor (if it is available) and if successful, advances the iterator. Conceptually, it behaves like the expressiondescriptor = *i++
, if an event descriptor is ready immediately (it does nothing otherwise)
The easiest way to understand the API is to compile and run the included
eventwatch
example program. This program dumps ASCII representations of
execution events to stdout
, as they are written by a execution daemon
running on the same host.
In eventwatch
, the event descriptors are fully decoded, but the event
payloads are only shown in hexdump form, because this simple program that does
not include pretty-printing logic for all event payload types. The program is
only 250 lines of code, and reading through it should explain how the various
API calls fit together.
The SDK also includes C++20
std::formatter
specializations which can fully decode event payloads into human-readable form.
These are used by the eventcap
utility program.
Using the API in your project
libmonad_event
is designed for third party integration, so it does not have
any library dependencies aside from a recent version of glibc. This also means
it has no dependency on the rest of the monad repository or on its build
system: the sole requirement is a C compiler supporting C23.
The "Getting start" guide to building the C example program discusses several ways to use the SDK library as a third-party dependency in your code. Alternatively, the source files that make up the library target can be copied into your own codebase. A Rust client library is also available.
API overview
Event ring APIs
API | Purpose |
---|---|
monad_event_ring_mmap | Given a file descriptor to an open event ring file, map its shared memory segments into the current process, initializing a struct monad_event_ring |
monad_event_ring_init_iterator | Given a pointer to a struct monad_event_ring , initialize an iterator that can read from the event ring |
monad_event_ring_try_copy | Given a specific sequence number, try to copy the event descriptor for it, if it hasn't been overwritten |
monad_event_ring_payload_peek | Get a zero-copy pointer to an event payload |
monad_event_ring_payload_check | Check if an event payload referred to by a zero-copy pointer has been overwritten |
monad_event_ring_memcpy | memcpy the event payload to a buffer, succeeding only if the payload is not expired |
monad_event_ring_get_last_error | Return a human-readable string describing the last error that occurred on this thread |
All functions which can fail will return an errno(3)
domain error code
diagnosing the reason for failure. The function
monad_event_ring_get_last_error
can be called to provide a human-readable
string explanation of what failed.