Skip to content

danish-mehmood/looperdooper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 

Repository files navigation

LooperDooper

An event loop library in C with cross-platform support and efficient event handling. This library provides a unified interface for handling I/O events, timers, and signals across different operating systems.

Features

  • Cross-Platform Support

    • Linux: epoll with signalfd integration
    • BSD/MacOS: kqueue with EVFILT_SIGNAL
    • Windows: select with IOCP integration
  • High-Performance Timer System

    • O(1) complexity timer wheel algorithm
    • Microsecond resolution
    • Support for one-shot and periodic timers
  • Robust Signal Handling

    • Unified API across all platforms
    • Platform-optimized implementations
    • Support for graceful shutdown patterns
  • Thread Pool Integration

    • Configurable worker count
    • Automatic task distribution
    • CPU-intensive task offloading

Building

# Build the library
gcc -I./include -c src/*.c

# Build examples
gcc -I./include -o echo_server examples/echo_server.c src/*.c
gcc -I./include -o thread_example examples/thread_example.c src/*.c -pthread

API Reference

Event Loop Management

// Create and destroy event loop
eventloop_t* eventloop_create(void);
eventloop_t* eventloop_create_with_threads(int num_threads);
void eventloop_destroy(eventloop_t* loop);

// Run the event loop
int eventloop_run(eventloop_t* loop);
void eventloop_stop(eventloop_t* loop);

Event Handling

// Add/remove/modify events
int eventloop_add_event(eventloop_t* loop, event_t* ev);
int eventloop_remove_event(eventloop_t* loop, event_t* ev);
int eventloop_modify_event(eventloop_t* loop, event_t* ev, uint32_t events);

Timer Management

// Add one-shot or periodic timer
int eventloop_add_timer(eventloop_t* loop, event_t* ev, uint64_t timeout_ms);
int eventloop_add_periodic_timer(eventloop_t* loop, event_t* ev, uint64_t interval_ms);

Signal Handling

// Add/remove signal handlers
int eventloop_add_signal(eventloop_t* loop, int signo, signal_callback_fn cb, void* arg);
int eventloop_remove_signal(eventloop_t* loop, int signo);

// Signal callback function type
typedef void (*signal_callback_fn)(eventloop_t* loop, int signo, void* arg);

Examples

Basic TCP Echo Server

#include "eventloop.h"
#include "network.h"

void on_client_data(eventloop_t* loop, socket_t* sock, void* data, size_t len, void* arg) {
    // Echo data back to client
    socket_write(sock, data, len);
}

int main() {
    eventloop_t* loop = eventloop_create();
    socket_t* server = socket_create(loop);

    socket_set_read_cb(server, on_client_data, NULL);
    socket_bind(server, NULL, 5000);
    socket_listen(server, SOMAXCONN);

    eventloop_run(loop);
    return 0;
}

Thread Pool Usage

#include "eventloop.h"

void heavy_computation(void* arg) {
    // CPU-intensive work here
}

int main() {
    eventloop_t* loop = eventloop_create_with_threads(4);

    // Submit task to thread pool
    eventloop_submit_task(loop, heavy_computation, arg);

    eventloop_run(loop);
    return 0;
}

Basic Signal Handler

#include "eventloop.h"
#include <signal.h>

void handle_sigint(eventloop_t* loop, int signo, void* arg) {
    printf("Received SIGINT (Ctrl+C)\n");
    eventloop_stop(loop);
}

int main() {
    eventloop_t* loop = eventloop_create();

    // Add SIGINT handler
    eventloop_add_signal(loop, SIGINT, handle_sigint, NULL);

    eventloop_run(loop);
    return 0;
}

Combining Signals with I/O Events

#include "eventloop.h"
#include <signal.h>
#include <unistd.h>

void handle_signal(eventloop_t* loop, int signo, void* arg) {
    printf("Received signal %d\n", signo);
    if (signo == SIGTERM) {
        eventloop_stop(loop);
    }
}

void handle_io(eventloop_t* loop, event_t* ev, void* arg) {
    char buffer[1024];
    ssize_t n = read(ev->fd, buffer, sizeof(buffer));
    if (n > 0) {
        printf("Read %zd bytes\n", n);
    }
}

int main() {
    eventloop_t* loop = eventloop_create();

    // Add signal handlers
    eventloop_add_signal(loop, SIGTERM, handle_signal, NULL);
    eventloop_add_signal(loop, SIGUSR1, handle_signal, NULL);

    // Add I/O event
    event_t ev;
    event_init(&ev, STDIN_FILENO, EV_READ, handle_io, NULL);
    eventloop_add_event(loop, &ev);

    eventloop_run(loop);
    eventloop_destroy(loop);
    return 0;
}

Platform-Specific Notes

Linux

  • Uses epoll() for I/O multiplexing
  • Integrates with signalfd() for signal handling
  • Supports all POSIX signals
// Linux-specific signal handling is efficient and reliable
// signalfd provides a file descriptor interface for signals
eventloop_add_signal(loop, SIGUSR1, handle_signal, NULL);
eventloop_add_signal(loop, SIGUSR2, handle_signal, NULL);

BSD/MacOS

  • Uses kqueue() with EVFILT_READ/WRITE
  • EVFILT_SIGNAL for signal handling
  • Supports all POSIX signals
// BSD systems use kqueue for signal handling
// Supports all standard POSIX signals
eventloop_add_signal(loop, SIGHUP, handle_signal, NULL);
eventloop_add_signal(loop, SIGTERM, handle_signal, NULL);

Windows

  • Uses select() for I/O multiplexing
  • Limited to console control signals
  • IOCP integration for better performance
// Windows has limited signal support
// Only console control handlers are supported
eventloop_add_signal(loop, SIGINT, handle_ctrl_c, NULL);  // Ctrl+C
eventloop_add_signal(loop, SIGBREAK, handle_break, NULL); // Ctrl+Break

Best Practices

  1. Signal Handling

    • Keep signal handlers minimal
    • Use the event loop to defer complex processing
    • Clean up signal handlers before destroying the loop
  2. Resource Management

    • Always check return values from API calls
    • Use provided cleanup functions
    • Remove events before closing file descriptors
  3. Thread Safety

    • Don't access event loop from multiple threads
    • Use thread pool for CPU-intensive tasks
    • Keep signal handlers thread-safe

Troubleshooting

  1. Event Loop Hangs

    • Check for unclosed file descriptors
    • Verify all events are properly removed
    • Ensure signal handlers are properly registered
  2. Memory Leaks

    • Use valgrind for leak detection
    • Implement proper cleanup in signal handlers
    • Check for resource leaks in callbacks
  3. Performance Issues

    • Monitor thread pool utilization
    • Use appropriate timer intervals
    • Check for blocking operations in callbacks

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run the test suite
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspired by libuv and libev
  • Built with modern C programming practices
  • Designed for production use

Limitations

  1. Windows Platform

    • Limited to console control signals only
    • No support for POSIX-style signals
    • Cannot handle application-specific signals
  2. Signal Queueing

    • Signal coalescing may occur under heavy load
    • Not all signals may be delivered if sent rapidly
    • Platform-specific queueing behavior varies
  3. Thread Safety

    • Signal handlers should be thread-safe
    • Avoid complex operations in signal handlers
    • Use the event loop to defer processing to the main thread

Releases

No releases published

Packages

 
 
 

Contributors

Languages