📨 chic 0.0.0
Realtime-safe channels in C
Loading...
Searching...
No Matches
mpmc.h File Reference

Multiple-producer, multiple-consumer channel. More...

#include "claim.h"

Go to the source code of this file.

Macros

#define make_mpmc(N, T)
 Convenience macro for allocating a new mpmc.
#define sizeof_mpmc(N, T)
 Convenience macro for calculating the size of a mpmc with certain parameters.
#define mpmc_send1(C, SRC)
 Convenience macro for sending a single item to a channel.
#define mpmc_nbsend1(C, SRC)
 Convenience macro for sending a single item to a channel.
#define mpmc_recv1(C, DST)
 Convenience macro for receiving a single item from a channel.
#define mpmc_nbrecv1(C, DST)
 Convenience macro for receiving a single item from a channel.

Functions

size_t mpmc_open (void *c, size_t nel, size_t elsize)
 Constructs a mpmc in-place, or calculates the needed allocation size for one.
struct mpmcmpmc_alloc (size_t nel, size_t elsize)
 Allocates a new mpmc using malloc() and opens it.
bool mpmc_close (struct mpmc *c)
 Closes a channel, forbidding any future send operations on it.
bool mpmc_send_init (struct mpmc *c, size_t n, struct claim *s)
 Claims space in the channel to be manually written into.
size_t mpmc_nbsend_init (struct mpmc *c, size_t n, struct claim *s)
 Claims up to an amount of space in the channel to be manually written into.
bool mpmc_send_fini (struct mpmc *c, struct claim *s)
 Commits a claim, indicating the item slots within are finished being written to and are ready to be received.
bool mpmc_nbsend_fini (struct mpmc *c, struct claim *s)
 Tries to commit a claim, indicating the item slots within have been written to and are ready to be received.
bool mpmc_send (struct mpmc *restrict c, size_t n, void *restrict src)
 Sends items to a channel.
size_t mpmc_nbsend (struct mpmc *restrict c, size_t n, void *restrict src)
 Sends whatever items will fit to a channel.
bool mpmc_sendv (struct mpmc *restrict c, size_t n,...)
 Sends items to a channel.
size_t mpmc_nbsendv (struct mpmc *restrict c, size_t n,...)
 Sends whatever items will fit to a channel.
bool mpmc_recv_init (struct mpmc *c, size_t n, struct claim *r)
 Claims space in the channel to be manually read from.
size_t mpmc_nbrecv_init (struct mpmc *c, size_t n, struct claim *r)
 Claims up to an amount of space in the channel to be manually read from.
bool mpmc_recv_fini (struct mpmc *c, struct claim *r)
 Commits a claim, indicating the item slots within have been read from and are ready to be overwritten.
bool mpmc_nbrecv_fini (struct mpmc *c, struct claim *r)
 Tries to commit a claim, indicating the item slots within have been read from and are safe to be overwritten.
bool mpmc_recv (struct mpmc *restrict c, size_t n, void *restrict dst)
 Receives items from a channel.
size_t mpmc_nbrecv (struct mpmc *restrict c, size_t n, void *restrict dst)
 Receives whatever items are available from a channel.
bool mpmc_recvv (struct mpmc *restrict c, size_t n,...)
 Receives items from a channel.
size_t mpmc_nbrecvv (struct mpmc *restrict c, size_t n,...)
 Receives whatever items are available from a channel.

Detailed Description

Multiple-producer, multiple-consumer channel.

Author
Fawn rubie.nosp@m.fawn.nosp@m.@gmai.nosp@m.l.co.nosp@m.m
Date
2026

Macro Definition Documentation

◆ make_mpmc

#define make_mpmc ( N,
T )
Value:
mpmc_alloc((N), sizeof(T))
struct mpmc * mpmc_alloc(size_t nel, size_t elsize)
Allocates a new mpmc using malloc() and opens it.

Convenience macro for allocating a new mpmc.

Parameters
NThe capacity of the channel; must be a nonzero power of 2
TThe type of a channel element
See also
mpmc_alloc

◆ mpmc_nbrecv1

#define mpmc_nbrecv1 ( C,
DST )
Value:
mpmc_nbrecv((C), 1, (DST))
size_t mpmc_nbrecv(struct mpmc *restrict c, size_t n, void *restrict dst)
Receives whatever items are available from a channel.

Convenience macro for receiving a single item from a channel.

See also
mpmc_nbrecv

◆ mpmc_nbsend1

#define mpmc_nbsend1 ( C,
SRC )
Value:
mpmc_nbsend((C), 1, (SRC))
size_t mpmc_nbsend(struct mpmc *restrict c, size_t n, void *restrict src)
Sends whatever items will fit to a channel.

Convenience macro for sending a single item to a channel.

See also
mpmc_nbsend

◆ mpmc_recv1

#define mpmc_recv1 ( C,
DST )
Value:
mpmc_recv((C), 1, (DST))
bool mpmc_recv(struct mpmc *restrict c, size_t n, void *restrict dst)
Receives items from a channel.

Convenience macro for receiving a single item from a channel.

See also
mpmc_recv

◆ mpmc_send1

#define mpmc_send1 ( C,
SRC )
Value:
mpmc_send((C), 1, (SRC))
bool mpmc_send(struct mpmc *restrict c, size_t n, void *restrict src)
Sends items to a channel.

Convenience macro for sending a single item to a channel.

See also
mpmc_send

◆ sizeof_mpmc

#define sizeof_mpmc ( N,
T )
Value:
mpmc_open(NULL, (N), sizeof(T))
size_t mpmc_open(void *c, size_t nel, size_t elsize)
Constructs a mpmc in-place, or calculates the needed allocation size for one.

Convenience macro for calculating the size of a mpmc with certain parameters.

Parameters
NThe capacity of the channel; must be a nonzero power of 2
TThe type of a channel element
See also
mpmc_open

Function Documentation

◆ mpmc_alloc()

struct mpmc * mpmc_alloc ( size_t nel,
size_t elsize )

Allocates a new mpmc using malloc() and opens it.

Parameters
nelThe minimum number of elements the channel should be able to hold; must be a nonzero power of 2
elsizeThe sizeof the type of a channel element
Returns
An owning pointer to a new mpmc allocated using malloc(), or nil if there was an error. If nil is returned, errno is set to indicate the reason why.
Exceptions
EINVALif nel is 0, or if elsize is 0 or not a power of 2
ENOMEMif out of memory
See also
mpmc_open

◆ mpmc_close()

bool mpmc_close ( struct mpmc * c)

Closes a channel, forbidding any future send operations on it.

Parameters
cThe channel to close
Returns
Whether or not the channel is ready to be deallocated. If false is returned, errno is set to indicate the reason why.
Exceptions
EINVALif chan is nil
EBUSYif chan has unreceived items

◆ mpmc_nbrecv()

size_t mpmc_nbrecv ( struct mpmc *restrict c,
size_t n,
void *restrict dst )

Receives whatever items are available from a channel.

Parameters
cThe channel to receive items from
nThe number of items to receive
dstWhere to receive the items into
Returns
How many items were received. If 0, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if dst is nil
EMSGSIZEif n is greater than the capacity of c
ENOMSGif there is nothing to receive from the channel
EPIPEif chan is closed and there are no more items to receive

◆ mpmc_nbrecv_fini()

bool mpmc_nbrecv_fini ( struct mpmc * c,
struct claim * r )

Tries to commit a claim, indicating the item slots within have been read from and are safe to be overwritten.

Claims for receiving must be committed according to their sequence number. If there are uncommitted claims for receiving sequenced prior to c, this function will immediately return.

Parameters
cThe channel in which to commit the claim
rThe claim to commit as received
Returns
Whether or not the claim was committed. If false, errno is set to indicate the reason why.
Exceptions
EINVALif either of c or r are nil
ECANCELEDif c is empty
EAGAINif there were uncommitted claims for receiving sequenced prior to r

◆ mpmc_nbrecv_init()

size_t mpmc_nbrecv_init ( struct mpmc * c,
size_t n,
struct claim * r )

Claims up to an amount of space in the channel to be manually read from.

Parameters
[in]cThe channel to claim space for receiving from
[in]nThe maximum number of item slots to claim for reading
[out]rA claim to initialize with one or two slices with total length n or less for reading directly from the channel.
Returns
The actual total length of r. If 0 is returned, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if r is nil
EMSGSIZEif n is greater than the capacity of c
ENOMSGif there is nothing to receive from the channel
EPIPEif chan is closed and there are no more items to receive
EOVERFLOWif the successfully claimed item slots wrap around the end of the channel's internal ringbuffer

◆ mpmc_nbrecvv()

size_t mpmc_nbrecvv ( struct mpmc *restrict c,
size_t n,
... )

Receives whatever items are available from a channel.

Parameters
cThe channel to receive items from
nThe number of items to receive
...Where to receive the items into
Returns
How many items were received. If 0, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil or if n is 0
EMSGSIZEif n is greater than the capacity of c
ENOMSGif there is nothing to receive from the channel
EPIPEif chan is closed and there are no more items to receive

◆ mpmc_nbsend()

size_t mpmc_nbsend ( struct mpmc *restrict c,
size_t n,
void *restrict src )

Sends whatever items will fit to a channel.

If the channel has less than n available item slots for writing, this function will send whatever items will fit. If there is no space available, this function will return 0.

Parameters
cThe channel to try to send items to
nThe maximum number of items to try to send
srcWhere to send the items from
Returns
How many items were sent. If 0, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if src is nil
EMSGSIZEif n is greater than the capacity of c
ENOBUFSif there is no room in the channel
EPIPEif chan is closed and can no longer be sent to

◆ mpmc_nbsend_fini()

bool mpmc_nbsend_fini ( struct mpmc * c,
struct claim * s )

Tries to commit a claim, indicating the item slots within have been written to and are ready to be received.

Claims for sending must be committed according to their sequence number. If there are uncommitted claims for sending sequenced prior to c, this function will immediately return.

Parameters
cThe channel in which to commit the claim
sThe claim to commit as sent
Returns
Whether or not the claim was committed. If false, errno is set to indicate the reason why.
Exceptions
EINVALif either of c or s are nil
ECANCELEDif c is empty
EAGAINif there were uncommitted claims for sending sequenced prior to s

◆ mpmc_nbsend_init()

size_t mpmc_nbsend_init ( struct mpmc * c,
size_t n,
struct claim * s )

Claims up to an amount of space in the channel to be manually written into.

If the channel has less than n available item slots for writing, this function will claim whatever space is available. If there is no space available, this function will return an empty claim.

Parameters
[in]cThe channel to claim space for sending into
[in]nThe number of item slots to claim for writing
[out]sA claim to initialize with one or two slices with total length n or less for writing directly into the channel.
Returns
The actual total length of s. If 0 is returned, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if s is nil
EMSGSIZEif n is greater than the capacity of c
ENOBUFSif there is no room in the channel
EPIPEif chan is closed and can no longer be sent to
EOVERFLOWif the successfully claimed item slots wrap around the end of the channel's internal ringbuffer

◆ mpmc_nbsendv()

size_t mpmc_nbsendv ( struct mpmc *restrict c,
size_t n,
... )

Sends whatever items will fit to a channel.

If the channel has less than n available item slots for writing, this function will send whatever items will fit. If there is no space available, this function will return 0.

Parameters
cThe channel to try to send items to
nThe maximum number of items to try to send
...Pointers to the items to send
Returns
How many items were sent. If 0, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil or if n is 0
EMSGSIZEif n is greater than the capacity of c
ENOBUFSif there is no room in the channel
EPIPEif chan is closed and can no longer be sent to

◆ mpmc_open()

size_t mpmc_open ( void * c,
size_t nel,
size_t elsize )

Constructs a mpmc in-place, or calculates the needed allocation size for one.

Parameters
[out]cThe address at which to construct a mpmc; may be nil
[in]nelThe number of elements the channel can hold; must be a nonzero power of 2
[in]elsizeThe sizeof the type of an element
Returns
The allocation size necessary to construct a mpmc with these parameters (if c was not nil, the size of the constructed mpmc). If there was an error, returns 0. If 0 is returned, errno is set to indicate the reason why.
Exceptions
EINVALif nel is 0, or if elsize is 0 or not a power of 2

◆ mpmc_recv()

bool mpmc_recv ( struct mpmc *restrict c,
size_t n,
void *restrict dst )

Receives items from a channel.

If the channel does not have n or more available items ready to be received, this function will busy-wait until there are.

Parameters
cThe channel to receive items from
nThe number of items to receive
dstWhere to receive the items into
Returns
Whether or not the items were received. If false, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if src is nil
EMSGSIZEif n is greater than the capacity of c
EPIPEif chan is closed and there are less than n items remaining to receive

◆ mpmc_recv_fini()

bool mpmc_recv_fini ( struct mpmc * c,
struct claim * r )

Commits a claim, indicating the item slots within have been read from and are ready to be overwritten.

Claims for receiving must be committed according to their sequence number. If there are uncommitted claims for receiving sequenced prior to r, this function will busy-wait until this is no longer the case.

Parameters
cThe channel in which to commit the claim
rThe claim to commit as received
Returns
Whether or not the claim was committed. If false, errno is set to indicate the reason why.
Exceptions
EINVALif either of c or r are nil
ECANCELEDif r is empty

◆ mpmc_recv_init()

bool mpmc_recv_init ( struct mpmc * c,
size_t n,
struct claim * r )

Claims space in the channel to be manually read from.

If the channel does not have n or more available item slots for reading, this function will busy-wait until there are.

Parameters
[in]cThe channel to claim space for receiving from
[in]nThe number of item slots to claim for reading
[out]rA claim to initialize with one or two slices with total length n for reading directly from the channel.
Returns
Whether or not r was initialized. If false is returned, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if r is nil
EMSGSIZEif n is greater than the capacity of c
EPIPEif chan is closed and there are no more items to receive
EOVERFLOWif the successfully claimed item slots wrap around the end of the channel's internal ringbuffer

◆ mpmc_recvv()

bool mpmc_recvv ( struct mpmc *restrict c,
size_t n,
... )

Receives items from a channel.

If the channel does not have n or more available items ready to be received, this function will busy-wait until there are.

Parameters
cThe channel to receive items from
nThe number of items to receive
...Where to receive the items into
Returns
Whether or not the items were received. If false, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil or if n is 0
EMSGSIZEif n is greater than the capacity of c
EPIPEif chan is closed and there are less than n items remaining to receive

◆ mpmc_send()

bool mpmc_send ( struct mpmc *restrict c,
size_t n,
void *restrict src )

Sends items to a channel.

If the channel does not have enough free space to send all n items, this function will busy-wait until there are.

Parameters
cThe channel to send items to
nThe number of items to send
srcWhere to send the items from
Returns
Whether or not the items were sent. If false, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if src is nil
EMSGSIZEif n is greater than the capacity of c
EPIPEif chan is closed and can no longer be sent to

◆ mpmc_send_fini()

bool mpmc_send_fini ( struct mpmc * c,
struct claim * s )

Commits a claim, indicating the item slots within are finished being written to and are ready to be received.

Claims for sending must be committed according to their sequence number. If there are uncommitted claims for sending sequenced prior to s, this function will busy-wait until this is no longer the case.

Parameters
cThe channel in which to commit the claim
sThe claim to commit as sent
Returns
Whether or not the claim was committed. If false, errno is set to indicate the reason why.
Exceptions
EINVALif either of c or s are nil
ECANCELEDif c is empty

◆ mpmc_send_init()

bool mpmc_send_init ( struct mpmc * c,
size_t n,
struct claim * s )

Claims space in the channel to be manually written into.

If the channel does not have n or more available item slots for writing, this function will busy-wait until there are.

Parameters
[in]cThe channel to claim space for sending into
[in]nThe number of item slots to claim for writing
[out]sA claim to initialize with one or two slices with total length n for writing directly into the channel.
Returns
Whether or not s was initialized. If false is returned, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil, if n is 0, or if s is nil
EMSGSIZEif n is greater than the capacity of c
EPIPEif chan is closed and can no longer be sent to
EOVERFLOWif the successfully claimed item slots wrap around the end of the channel's internal ringbuffer

◆ mpmc_sendv()

bool mpmc_sendv ( struct mpmc *restrict c,
size_t n,
... )

Sends items to a channel.

If the channel does not have enough free space to send all n items, this function will busy-wait until there are.

Parameters
cThe channel to send items to
nThe number of items to send
...Pointers to the items to send
Returns
Whether or not the items were sent. If false, errno is set to indicate the reason why.
Exceptions
EINVALif c is nil or if n is 0
EMSGSIZEif n is greater than the capacity of c
EPIPEif chan is closed and can no longer be sent to