xtc_credit(3)

---

xtc_credit(3)

sliding-window credit regulator (in-flight flow control)

XTC_CREDIT(3) Library Functions Manual XTC_CREDIT(3)

xtc_credit_create, xtc_credit_destroy, xtc_credit_acquire, xtc_credit_try_acquire, xtc_credit_release, xtc_credit_in_flight, xtc_credit_peak, xtc_credit_windowsliding-window credit regulator (in-flight flow control)

library “libxtc”

#include <xtc_credit.h>

int
xtc_credit_create(unsigned window, xtc_credit_t **out);

void
xtc_credit_destroy(xtc_credit_t *c);

int
xtc_credit_acquire(xtc_credit_t *c, int64_t timeout_ns);

int
xtc_credit_try_acquire(xtc_credit_t *c);

int
xtc_credit_release(xtc_credit_t *c);

unsigned
xtc_credit_in_flight(const xtc_credit_t *c);

unsigned
xtc_credit_peak(const xtc_credit_t *c);

unsigned
xtc_credit_window(const xtc_credit_t *c);

A credit regulator caps the number of operations a producer keeps IN FLIGHT -- issued but not yet acknowledged -- at once. Take a credit before issuing an operation with (), return it when the operation's acknowledgement comes back with (); when credits are exhausted a further xtc_credit_acquire() blocks the calling fiber until an ack frees one.

This is the credit-based flow-control pattern, and it is transport-agnostic: it works over a request/reply RPC to another process, over socket writes, over disk operations -- anywhere a fast issuer can outrun a slower acknowledger. The demand channel (xtc_chan(3)) is its producer/consumer-channel sibling; this regulator is for the request-issue / ack-return sliding window.

There is direct precedent in the Erlang/OTP ecosystem: the ‘:jobs’ regulator, RabbitMQ's ‘credit_flow’, and GenStage's ‘max_demand/‘min_demand’ all express exactly this window. OTP has no single named behaviour for it -- it is a gen_server plus an integer counter -- which is what this regulator packages, adding the peak-in-flight high-water mark the hand-rolled version usually drops.

() sizes the window (maximum in flight); () must be greater than zero. xtc_credit_acquire() takes one credit, blocking up to timeout_ns (0 tries once, a negative value blocks indefinitely); () takes one only if immediately available. xtc_credit_release() returns a credit and wakes one waiter.

() reports the operations currently outstanding; () reports the high-water mark since creation (useful for tuning the window); and () returns the configured window size.

Built on xtc_sync(3) semaphores, so a producer running inside a fiber parks its fiber -- not the OS thread -- while waiting for a credit.

xtc_credit_create(), xtc_credit_acquire(), xtc_credit_try_acquire(), and xtc_credit_release() return XTC_OK or a negative XTC_E_* code; xtc_credit_acquire() and xtc_credit_try_acquire() return XTC_E_AGAIN when no credit is available, and xtc_credit_release() returns XTC_E_INVAL on a release with no matching acquire.

xtc_credit_in_flight(), xtc_credit_peak(), and xtc_credit_window() return counts.

xtc_credit_destroy() returns no value.

xtc_credit_t *cw;
xtc_credit_create(4, &cw);            /* at most 4 in flight */

/* Issue side: take a credit, send a request. */
xtc_credit_acquire(cw, -1);
send_request(peer, req);              /* reply carries the credit back */

/* Ack side: when a reply arrives, return the credit. */
xtc_credit_release(cw);               /* unblocks a waiting issuer */

xtc_chan(3), xtc_sync(3), xtc_proc(3), xtc(7)

July 10, 2026 Debian

View the mdoc source