What is libevent?
libevent is a battle-tested portable event notification library for building high-performance asynchronous I/O applications. It provides a unified API over the fastest available I/O multiplexing mechanism on each platform, so your code runs optimally on Linux, macOS, BSD, and Windows without change.
The core abstractions are:
- Event Base — the event loop dispatcher. Everything runs through a base.
- Event — a registered file descriptor + event type (read/write/signal) + callback.
- Bufferevent — buffered I/O layer for TCP streams with automatic read/write buffering.
- Evbuffer — dynamic buffer for efficient I/O without copying.
- Async DNS — non-blocking hostname resolution integrated with the event loop.
- HTTP server — a production-grade built-in HTTP/1.1 server and client.
libevent is used in production by Memcached, Tor, Varnish, tmux, libvirt, and the Chromium legacy network stack.
Requires libevent-dev. Ubuntu/Debian: sudo apt install libevent-dev. macOS: brew install libevent. Windows: provided via vcpkg or prebuilt DLL.
Backends
libevent automatically selects the best available I/O notification backend at runtime. You can query or force a specific one:
| Backend | Platform | Notes |
|---|---|---|
| epoll | Linux | Best performance, edge or level-triggered |
| kqueue | macOS / BSD | Native kernel event queue |
| IOCP | Windows | Completion ports, native async |
| poll | Portable fallback | POSIX, O(n) but reliable |
| select | Oldest fallback | Limited to 1024 fds on most systems |
uses libevent;
var Base := NewBase;
WriteLn('Active backend: ', GetMethod(Base)); { epoll, kqueue, etc. }
{ Force a specific backend }
var Base2 := NewBaseMethod('epoll');
{ List all available backends on this machine }
var Methods := SupportedMethods;
for I := 0 to Length(Methods) - 1 do
WriteLn(Methods[I]);
vs Other Event Loops
libuv (Node.js) is newer and more complete: it adds async file I/O and child process management. libevent is older, more battle-tested, and ships with a built-in HTTP server and async DNS. Prefer libevent when you need HTTP or DNS out of the box.
libev is lighter and faster for raw event dispatch but has fewer built-in features (no HTTP, no DNS). Boost.Asio is a C++ library with a richer async model (coroutines, strands) but is C++ only. libevent is the best choice for C-interop from PascalAI.
Types
TLEEventType enum
| Value | Hex | Meaning |
|---|---|---|
| etRead | $02 | Fire when fd is readable |
| etWrite | $04 | Fire when fd is writable |
| etSignal | $08 | UNIX signal event |
| etPersist | $10 | Re-add event after each trigger (persistent) |
| etEdge | $20 | Edge-triggered mode (epoll ET) |
| etTimeout | $01 | Timer / timeout event |
TLEHTTPType enum
| Value | Hex | HTTP Method |
|---|---|---|
| htGET | $0010 | GET |
| htPOST | $0020 | POST |
| htPUT | $0040 | PUT |
| htPATCH | $0080 | PATCH |
| htDELETE | $0100 | DELETE |
| htHEAD | $0200 | HEAD |
| htOPTIONS | $0400 | OPTIONS |
| htAny | $FFFF | Match any method |
TLEHTTPRequest record
type TLEHTTPRequest = record
Method : string; { 'GET', 'POST', etc. }
URI : string; { full URI including query string }
Path : string; { path component only }
Query : string; { query string (after '?') }
Major : Integer; { HTTP major version (1) }
Minor : Integer; { HTTP minor version (0 or 1) }
RemoteHost : string; { client IP address }
RemotePort : Integer; { client port }
Body : string; { request body }
ContentLen : Int64; { Content-Length header value }
end;
API Reference
Event Base
Events
Bufferevent (TCP streams with auto-buffering)
Connection Listener
HTTP Server
Async DNS
Info
Simple HTTP Server
The built-in HTTP server is the easiest way to serve HTTP/1.1 from a PascalAI program. Bind, set a timeout, register a callback, then enter the event loop:
uses libevent;
var
Base : TLEBase;
HTTP : TLEHTTP;
Req : TLEHTTPRequest;
begin
Base := NewBase;
WriteLn('Backend: ', GetMethod(Base)); { epoll, kqueue, etc. }
HTTP := NewHTTP(Base);
HTTPBind(HTTP, '0.0.0.0', 8080);
HTTPSetTimeout(HTTP, 30);
{ Register a handler via callback system }
Dispatch(Base); { run event loop — blocks until LoopBreak }
FreeHTTP(HTTP);
FreeBase(Base);
end.
Inside an HTTP callback (invoked by the runtime when a request arrives), parse the request and send a reply:
{ Inside the HTTP request callback: }
var Info := HTTPGetRequest(Req);
WriteLn(Info.Method, ' ', Info.Path);
{ Read a header }
var CT := HTTPGetHeader(Req, 'Content-Type');
{ Add response headers and send }
HTTPAddHeader(Req, 'Content-Type', 'application/json');
HTTPAddHeader(Req, 'X-Powered-By', 'PascalAI');
HTTPSendReply(Req, 200, 'OK', '{"status":"ok"}');
TCP Echo Server (Bufferevent)
For raw TCP, use NewListener to accept connections and NewBufEvent to wrap each socket with automatic read/write buffering. The callback receives data as soon as it is available:
uses libevent;
var
Base : TLEBase;
L : TLEListener;
BE : TLEBufEvent;
begin
Base := NewBase;
{ Listen on port 9000, backlog 128 }
L := NewListener(Base, '0.0.0.0', 9000, 128);
{ In accept callback, wrap each new fd: }
BE := NewBufEvent(Base, NewFD);
BufEventSetCallbacks(BE, 'myReadCB');
BufEventEnable(BE, $02); { etRead }
Dispatch(Base);
FreeListener(L);
FreeBase(Base);
end.
{ Read callback body (registered as 'myReadCB'): }
var Data : string;
Data := BufEventRead(BE, 4096);
BufEventWrite(BE, Data); { echo back to client }
Timer and Signal Events
uses libevent;
var
Base : TLEBase;
Timer : TLEEvent;
Sig : TLEEvent;
begin
Base := NewBase;
{ One-shot timer fires after 5000 ms }
Timer := NewTimer(Base);
AddEvent(Timer, 5000);
{ Persistent SIGTERM handler }
Sig := NewSignalEvent(Base, 15); { SIGTERM }
AddEvent(Sig, -1); { no timeout }
Dispatch(Base);
FreeEvent(Timer);
FreeEvent(Sig);
FreeBase(Base);
end.
Async DNS Resolution
uses libevent;
var
Base : TLEBase;
DNS : TLEDNSBase;
begin
Base := NewBase;
DNS := NewDNS(Base);
DNSResolve(DNS, 'api.github.com'); { non-blocking }
{ result arrives in DNS callback during Dispatch }
Dispatch(Base);
FreeDNS(DNS);
FreeBase(Base);
end.
Install
ppm install libevent
Package Info
Used By
Tor
Varnish
tmux
libvirt
Chromium (legacy)
Event Base
- NewBase
- NewBaseMethod
- Dispatch
- DispatchOnce
- LoopBreak
- LoopExit
- FreeBase
- GetMethod
Events
- NewEvent
- NewTimer
- NewSignalEvent
- AddEvent
- DelEvent
- FreeEvent
- EventPending
Bufferevent
- NewBufEvent
- NewBufEventTLS
- BufEventConnect
- BufEventEnable
- BufEventWrite
- BufEventRead
- BufEventSetCallbacks
- FreeBufEvent
HTTP Server
- NewHTTP / FreeHTTP
- HTTPBind
- HTTPSetTimeout
- HTTPGetRequest
- HTTPGetHeader
- HTTPSendReply
- HTTPAddHeader
Listener & DNS
- NewListener
- FreeListener
- NewDNS
- DNSResolve
- FreeDNS
- SupportedMethods
- LibEventVersion
See Also
- curl (HTTP client)
- zmq (messaging)
- websocket
- http-client