Usage Guide
📨 Message Event Handler
Create event handlers by deriving from event_handler::event_handler. The base class uses an event looper to continuously and asynchronously poll and execute messages from an event queue.
Basic Example
#include "libevent.h"
class TestHandler : public event_handler::event_handler
{
public:
TestHandler() : event_handler::event_handler() {}
void print_message(std::string s)
{
std::cout << s << std::endl;
}
void do_heavy_work(int ith)
{
for (int i = 0; i < 1000; i++)
{
// do something
int val = i & 1;
}
std::cout << "Done work #" << ith << std::endl;
}
void tick()
{
std::cout << "Tick every 1 second..." << std::endl;
this->post_delayed_event(1000U, &TestHandler::tick);
}
};
// Usage
std::shared_ptr<TestHandler> handler = std::make_shared<TestHandler>();
// Post delayed message (2 seconds)
handler->post_delayed_event(2000U, &TestHandler::print_message,
std::string("Delayed message"));
// Post regular message
handler->post_event(&TestHandler::print_message,
std::string("Hello event handler"));
// Post repeated message (5 times, every 1 second)
handler->post_repeated_event(5, 1000U, &TestHandler::repated_work);
🔗 Signals and Slots
Qt-style signal-slot mechanism for decoupled communication between objects.
Basic Example
#include "libevent.h"
// Signal sender
class Sender
{
public:
sigslot::signal<std::string> message_notification;
void boardcast_message(std::string mess)
{
message_notification(mess);
}
};
// Signal receiver
class Listener : public sigslot::base_slot
{
public:
void on_boardcast_received(std::string mess)
{
std::cout << "Received: " << mess << std::endl;
}
};
// Usage
Sender sender;
Listener listener;
// Connect signal to slot
sender.message_notification.connect(&listener, &Listener::on_boardcast_received);
// Emit signal
sender.boardcast_message("Hello from Sender");
// Disconnect
sender.message_notification.disconnect(&listener);
Lambda Connections
sigslot::signal<> test_sig_lambda;
test_sig_lambda.connect([]() {
std::cout << "Lambda activated" << std::endl;
});
test_sig_lambda();
test_sig_lambda.disconnect_all_callable();
⏰ Time Events
Thread-safe timer mechanism using POSIX APIs. Supports one-shot and periodic timers.
Example
#include "libevent.h"
time_event::timer my_timer;
// Set duration
my_timer.set_duration(1000); // 1 second
// Add callback
my_timer.add_callback([]() {
std::cout << "Timer expired!" << std::endl;
});
// Start timer
try {
my_timer.start(5); // repeat 5 times
// my_timer.start(0); // one-shot
// my_timer.start(); // repeat forever
}
catch (const std::runtime_error& e) {
std::cerr << "Timer error: " << e.what() << std::endl;
}
// Stop timer
my_timer.stop();
🎯 Once Events
Control function execution based on various conditions like call count, value changes, or time intervals.
once_per_life
once_event::once_per_life init_flag;
// Called only once
init_flag.call_once([]() {
std::cout << "Initialize resources" << std::endl;
});
once_per_n_times
once_event::once_per_n_times every_third(3);
for (int i = 1; i <= 10; ++i) {
// Executed on calls 3, 6, 9
every_third.call_if_due([]() {
std::cout << "Executed!" << std::endl;
});
}
once_per_value
once_event::once_per_value<int> value_monitor;
value_monitor.on_value_change(5, [](int val) {
std::cout << "New value: " << val << std::endl;
}); // Prints: New value: 5
value_monitor.on_value_change(5, [](int val) {
std::cout << "New value: " << val << std::endl;
}); // Does nothing (unchanged)
once_per_interval
once_event::once_per_interval rate_limiter(1000); // 1 second
bool executed = rate_limiter.call([]() {
std::cout << "Rate-limited action" << std::endl;
});
🔄 Toggle Events
Synchronization mechanism that triggers a callback only once when a condition becomes true.
Basic Usage
toggle_event::toggle_event toggle;
// Trigger once
toggle.trigger_if_not_set([]() {
std::cout << "Event triggered!" << std::endl;
}); // Prints
// Subsequent calls ignored
toggle.trigger_if_not_set([]() {
std::cout << "Won't print" << std::endl;
}); // Does nothing
// Reset and trigger again
toggle.reset();
toggle.trigger_if_not_set([]() {
std::cout << "Triggered again!" << std::endl;
});
Blocking Wait
toggle_event::toggle_event event;
// Wait for event (blocking)
std::thread waiter([&event]() {
event.wait(); // Blocks until triggered
std::cout << "Event received!" << std::endl;
});
// Trigger from another thread
std::this_thread::sleep_for(std::chrono::seconds(2));
event.trigger_if_not_set([]() {
std::cout << "Triggering event" << std::endl;
});
Wait with Timeout
toggle_event::toggle_event event;
bool result = event.wait_for(2000); // 2 second timeout
if (result) {
std::cout << "Event triggered" << std::endl;
} else {
std::cout << "Timeout" << std::endl;
}
📁 File Descriptor Events
Monitor multiple file descriptors using poll-based I/O with event-driven callbacks.
Basic Example
#include "libevent.h"
fd_event::fd_event_manager manager;
// Add file descriptor with callback
manager.add_fd(
socket_fd,
static_cast<short>(fd_event::event_type::READ),
[](int fd, short revents, void* user_data) {
if (revents & POLLIN) {
char buffer[1024];
ssize_t n = read(fd, buffer, sizeof(buffer));
// Process data...
}
},
nullptr,
"my_socket"
);
// Main event loop
while (running) {
int ret = manager.wait_and_process(1000); // 1 second timeout
if (ret < 0) {
std::cerr << "Error: " << manager.get_last_error() << std::endl;
}
}
With User Data
struct Context {
int counter;
std::string name;
};
Context my_context = {0, "MyContext"};
manager.add_fd(
fd,
POLLIN,
[](int fd, short revents, void* user_data) {
Context* ctx = static_cast<Context*>(user_data);
ctx->counter++;
std::cout << ctx->name << " event #" << ctx->counter << std::endl;
},
&my_context,
"context_fd"
);
📡 Signal Events
Clean C++ wrapper around POSIX signal handling APIs.
Basic Signal Handler
#include "libevent.h"
void handle_interrupt(int signum) {
std::cout << "Caught signal " << signum << std::endl;
std::cout << "Gracefully shutting down..." << std::endl;
}
// Set handler
signal_event::set_signal_handler(SIGINT, handle_interrupt);
// Reset to default
signal_event::reset_signal_handler(SIGINT);
// Ignore signal
signal_event::ignore_signal(SIGUSR1);
Extended Signal Handler
void extended_handler(int signum, siginfo_t* info, void* context) {
std::cout << "Signal: " << signal_event::get_signal_name(signum) << std::endl;
std::cout << "Sender PID: " << info->si_pid << std::endl;
std::cout << "Sender UID: " << info->si_uid << std::endl;
}
signal_event::set_signal_handler_ex(SIGUSR1, extended_handler);
Blocking and Waiting
// Block signals
signal_event::block_signals({SIGUSR1, SIGUSR2});
// Wait for signal (infinite)
int received = signal_event::wait_for_signal({SIGUSR1, SIGUSR2});
// Wait with timeout
received = signal_event::wait_for_signal({SIGUSR1, SIGUSR2}, 5000);
// Check if pending
if (signal_event::is_signal_pending(SIGUSR1)) {
std::cout << "SIGUSR1 is pending" << std::endl;
}
📂 File System Events
Monitor file system changes using Linux inotify API. Similar to Python's pyinotify.
Basic Example
#include "libevent.h"
// Custom event handler
class my_event_handler : public fs_event::process_event
{
public:
void process_IN_CREATE(const fs_event::fs_event_info& event) override
{
std::cout << "Created: " << event.get_full_path() << std::endl;
}
void process_IN_MODIFY(const fs_event::fs_event_info& event) override
{
std::cout << "Modified: " << event.get_full_path() << std::endl;
}
void process_IN_DELETE(const fs_event::fs_event_info& event) override
{
std::cout << "Deleted: " << event.get_full_path() << std::endl;
}
};
int main()
{
// Create watch manager
auto wm = std::make_shared<fs_event::watch_manager>();
// Create event handler
auto handler = std::make_shared<my_event_handler>();
// Define events to monitor
auto mask = fs_event::fs_event_type::CREATE |
fs_event::fs_event_type::MODIFY |
fs_event::fs_event_type::DELETE;
// Add watch (recursive)
wm->add_watch("/path/to/watch", mask, true);
// Create notifier and start event loop
auto notifier = std::make_shared<fs_event::notifier>(wm, handler);
notifier->loop(); // Blocking
return 0;
}
Non-Blocking Mode
auto notifier = std::make_shared<fs_event::notifier>(wm, handler);
bool running = true;
while (running) {
// Process events with timeout
int count = notifier->process_events(1000);
if (count > 0) {
std::cout << "Processed " << count << " events" << std::endl;
}
// Do other work...
}