Event Handle

This API provides a lightweight, cross-platform event system designed for building asynchronous and event-driven applications in C and C++. It abstracts a central event queue capable of handling multiple event types—such as I/O, timers, signals, and custom user-defined events—through a simple polling or blocking interface. Each event is represented by fossil_sys_event_t, which includes a type, identifier, and arbitrary payload, making the system flexible enough for everything from low-level system notifications to high-level application messaging. The API supports both non-blocking (poll) and blocking (wait) consumption patterns, enabling integration into game loops, servers, or reactive pipelines. The C++ wrapper (fossil::sys::Event) simplifies usage further with static methods, allowing clean, minimal syntax while preserving the same underlying behavior.

HEADER REFERENCE #

#ifndef FOSSIL_SYS_EVENT_H
#define FOSSIL_SYS_EVENT_H

#include <stdint.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ------------------------------------------------------
 * Event Types
 * ----------------------------------------------------- */
typedef enum {
    FOSSIL_EVENT_NONE,
    FOSSIL_EVENT_IO,
    FOSSIL_EVENT_TIMER,
    FOSSIL_EVENT_SIGNAL,
    FOSSIL_EVENT_CUSTOM
} fossil_sys_event_type_t;

/* ------------------------------------------------------
 * Event Structure
 * ----------------------------------------------------- */
typedef struct {
    const char* id;                // string ID for AI/tracking
    fossil_sys_event_type_t type;
    void* payload;                 // user-defined data
    size_t size;                   // payload size
} fossil_sys_event_t;

/* ------------------------------------------------------
 * Event API
 * ----------------------------------------------------- */

/**
 * Initialize the event subsystem.
 * Must be called before using any other event functions.
 * 
 * @return 0 on success, negative value on failure
 */
int fossil_sys_event_init(void);

/**
 * Poll for events without blocking.
 * Retrieves the next available event if one exists.
 * 
 * @param out_event Pointer to event structure to fill with event data
 * @return 0 if event was retrieved, 1 if no event available, negative on error
 */
int fossil_sys_event_poll(fossil_sys_event_t* out_event);

/**
 * Wait for the next event with optional timeout.
 * Blocks until an event is available or timeout expires.
 * 
 * @param out_event Pointer to event structure to fill with event data
 * @param timeout_ms Maximum time to wait in milliseconds (0 = infinite)
 * @return 0 on success, 1 on timeout, negative on error
 */
int fossil_sys_event_wait(fossil_sys_event_t* out_event, uint32_t timeout_ms);

/**
 * Post a custom event to the event queue.
 * The payload is copied internally if necessary.
 * 
 * @param id String identifier for the event
 * @param payload User-defined data (can be NULL)
 * @param size Size of payload in bytes
 * @return 0 on success, negative on failure
 */
int fossil_sys_event_post(const char* id, void* payload, size_t size);

/**
 * Shutdown the event subsystem and release all resources.
 * Should be called when event system is no longer needed.
 */
void fossil_sys_event_shutdown(void);

#ifdef __cplusplus
}

namespace fossil::sys {

class Event {
public:
    /**
     * Initialize the event subsystem.
     * Must be called before using any other event functions.
     * 
     * @return 0 on success, negative value on failure
     */
    static int init(void) {
        return fossil_sys_event_init();
    }

    /**
     * Poll for events without blocking.
     * Retrieves the next available event if one exists.
     * 
     * @param out_event Pointer to event structure to fill with event data
     * @return 0 if event was retrieved, 1 if no event available, negative on error
     */
    static int poll(fossil_sys_event_t* out_event) {
        return fossil_sys_event_poll(out_event);
    }

    /**
     * Wait for the next event with optional timeout.
     * Blocks until an event is available or timeout expires.
     * 
     * @param out_event Pointer to event structure to fill with event data
     * @param timeout_ms Maximum time to wait in milliseconds (0 = infinite)
     * @return 0 on success, 1 on timeout, negative on error
     */
    static int wait(fossil_sys_event_t* out_event, uint32_t timeout_ms) {
        return fossil_sys_event_wait(out_event, timeout_ms);
    }

    /**
     * Post a custom event to the event queue.
     * The payload is copied internally if necessary.
     * 
     * @param id String identifier for the event
     * @param payload User-defined data (can be NULL)
     * @param size Size of payload in bytes
     * @return 0 on success, negative on failure
     */
    static int post(const char* id, void* payload, size_t size) {
        return fossil_sys_event_post(id, payload, size);
    }

    /**
     * Shutdown the event subsystem and release all resources.
     * Should be called when event system is no longer needed.
     */
    static void shutdown(void) {
        fossil_sys_event_shutdown();
    }
};

} // namespace fossil::sys

#endif

#endif /* FOSSIL_SYS_EVENT_H */

SAMPLE CODE C #

#include "fossil/sys/event.h"
#include <stdio.h>
#include <string.h>

int main(void)
{
    if (fossil_sys_event_init() != 0) {
        printf("Failed to initialize event system\n");
        return 1;
    }

    /* Post a custom event */
    const char *message = "Hello Event System";
    fossil_sys_event_post("custom.message", (void*)message, strlen(message) + 1);

    /* Event loop */
    fossil_sys_event_t event;

    while (1) {
        int rc = fossil_sys_event_wait(&event, 1000); /* wait up to 1 second */

        if (rc == 1) {
            printf("Timeout, no event\n");
            continue;
        } else if (rc < 0) {
            printf("Error occurred\n");
            break;
        }

        /* Handle event */
        switch (event.type) {
            case FOSSIL_EVENT_CUSTOM:
                printf("Custom Event [%s]: %s\n",
                       event.id,
                       (char*)event.payload);
                break;

            case FOSSIL_EVENT_IO:
                printf("IO Event received\n");
                break;

            case FOSSIL_EVENT_TIMER:
                printf("Timer Event received\n");
                break;

            default:
                printf("Unknown Event\n");
                break;
        }

        break; /* exit after one event for demo */
    }

    fossil_sys_event_shutdown();
    return 0;
}

SAMPLE CODE C++ #

#include "fossil/sys/event.h"
#include <iostream>
#include <cstring>

using namespace fossil::sys;

int main()
{
    if (Event::init() != 0) {
        std::cerr << "Failed to initialize event system\n";
        return 1;
    }

    /* Post a custom event */
    const char* msg = "Hello from C++ Event API";
    Event::post("custom.message", (void*)msg, std::strlen(msg) + 1);

    fossil_sys_event_t event;

    /* Simple event loop */
    while (true) {
        int rc = Event::wait(&event, 1000);

        if (rc == 1) {
            std::cout << "Timeout...\n";
            continue;
        } else if (rc < 0) {
            std::cerr << "Event error\n";
            break;
        }

        if (event.type == FOSSIL_EVENT_CUSTOM) {
            std::cout << "Custom Event [" << event.id << "]: "
                      << static_cast<char*>(event.payload) << "\n";
        } else {
            std::cout << "Other event received\n";
        }

        break; /* demo exit */
    }

    Event::shutdown();
    return 0;
}

What are your feelings

Updated on March 24, 2026