|
rpm-build |
4aa2fb |
#ifndef chan_h
|
|
rpm-build |
4aa2fb |
#define chan_h
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
#include <pthread.h>
|
|
rpm-build |
4aa2fb |
#include <stdint.h>
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
#include "queue.h"
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Defines a thread-safe communication pipe. Channels are either buffered or
|
|
rpm-build |
4aa2fb |
// unbuffered. An unbuffered channel is synchronized. Receiving on either type
|
|
rpm-build |
4aa2fb |
// of channel will block until there is data to receive. If the channel is
|
|
rpm-build |
4aa2fb |
// unbuffered, the sender blocks until the receiver has received the value. If
|
|
rpm-build |
4aa2fb |
// the channel is buffered, the sender only blocks until the value has been
|
|
rpm-build |
4aa2fb |
// copied to the buffer, meaning it will block if the channel is full.
|
|
rpm-build |
4aa2fb |
typedef struct chan_t
|
|
rpm-build |
4aa2fb |
{
|
|
rpm-build |
4aa2fb |
// Buffered channel properties
|
|
rpm-build |
4aa2fb |
queue_t* queue;
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Unbuffered channel properties
|
|
rpm-build |
4aa2fb |
pthread_mutex_t r_mu;
|
|
rpm-build |
4aa2fb |
pthread_mutex_t w_mu;
|
|
rpm-build |
4aa2fb |
void* data;
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Shared properties
|
|
rpm-build |
4aa2fb |
pthread_mutex_t m_mu;
|
|
rpm-build |
4aa2fb |
pthread_cond_t r_cond;
|
|
rpm-build |
4aa2fb |
pthread_cond_t w_cond;
|
|
rpm-build |
4aa2fb |
int closed;
|
|
rpm-build |
4aa2fb |
int r_waiting;
|
|
rpm-build |
4aa2fb |
int w_waiting;
|
|
rpm-build |
4aa2fb |
} chan_t;
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Allocates and returns a new channel. The capacity specifies whether the
|
|
rpm-build |
4aa2fb |
// channel should be buffered or not. A capacity of 0 will create an unbuffered
|
|
rpm-build |
4aa2fb |
// channel. Sets errno and returns NULL if initialization failed.
|
|
rpm-build |
4aa2fb |
chan_t* chan_init(size_t capacity);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Releases the channel resources.
|
|
rpm-build |
4aa2fb |
void chan_dispose(chan_t* chan);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Once a channel is closed, data cannot be sent into it. If the channel is
|
|
rpm-build |
4aa2fb |
// buffered, data can be read from it until it is empty, after which reads will
|
|
rpm-build |
4aa2fb |
// return an error code. Reading from a closed channel that is unbuffered will
|
|
rpm-build |
4aa2fb |
// return an error code. Closing a channel does not release its resources. This
|
|
rpm-build |
4aa2fb |
// must be done with a call to chan_dispose. Returns 0 if the channel was
|
|
rpm-build |
4aa2fb |
// successfully closed, -1 otherwise.
|
|
rpm-build |
4aa2fb |
int chan_close(chan_t* chan);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Returns 0 if the channel is open and 1 if it is closed.
|
|
rpm-build |
4aa2fb |
int chan_is_closed(chan_t* chan);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Sends a value into the channel. If the channel is unbuffered, this will
|
|
rpm-build |
4aa2fb |
// block until a receiver receives the value. If the channel is buffered and at
|
|
rpm-build |
4aa2fb |
// capacity, this will block until a receiver receives a value. Returns 0 if
|
|
rpm-build |
4aa2fb |
// the send succeeded or -1 if it failed.
|
|
rpm-build |
4aa2fb |
int chan_send(chan_t* chan, void* data);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Receives a value from the channel. This will block until there is data to
|
|
rpm-build |
4aa2fb |
// receive. Returns 0 if the receive succeeded or -1 if it failed.
|
|
rpm-build |
4aa2fb |
int chan_recv(chan_t* chan, void** data);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Returns the number of items in the channel buffer. If the channel is
|
|
rpm-build |
4aa2fb |
// unbuffered, this will return 0.
|
|
rpm-build |
4aa2fb |
int chan_size(chan_t* chan);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// A select statement chooses which of a set of possible send or receive
|
|
rpm-build |
4aa2fb |
// operations will proceed. The return value indicates which channel's
|
|
rpm-build |
4aa2fb |
// operation has proceeded. If more than one operation can proceed, one is
|
|
rpm-build |
4aa2fb |
// selected randomly. If none can proceed, -1 is returned. Select is intended
|
|
rpm-build |
4aa2fb |
// to be used in conjunction with a switch statement. In the case of a receive
|
|
rpm-build |
4aa2fb |
// operation, the received value will be pointed to by the provided pointer. In
|
|
rpm-build |
4aa2fb |
// the case of a send, the value at the same index as the channel will be sent.
|
|
rpm-build |
4aa2fb |
int chan_select(chan_t* recv_chans[], int recv_count, void** recv_out,
|
|
rpm-build |
4aa2fb |
chan_t* send_chans[], int send_count, void* send_msgs[]);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
// Typed interface to send/recv chan.
|
|
rpm-build |
4aa2fb |
int chan_send_int32(chan_t*, int32_t);
|
|
rpm-build |
4aa2fb |
int chan_send_int64(chan_t*, int64_t);
|
|
rpm-build |
4aa2fb |
#if ULONG_MAX == 4294967295UL
|
|
rpm-build |
4aa2fb |
# define chan_send_int(c, d) chan_send_int64(c, d)
|
|
rpm-build |
4aa2fb |
#else
|
|
rpm-build |
4aa2fb |
# define chan_send_int(c, d) chan_send_int32(c, d)
|
|
rpm-build |
4aa2fb |
#endif
|
|
rpm-build |
4aa2fb |
int chan_send_double(chan_t*, double);
|
|
rpm-build |
4aa2fb |
int chan_send_buf(chan_t*, void*, size_t);
|
|
rpm-build |
4aa2fb |
int chan_recv_int32(chan_t*, int32_t*);
|
|
rpm-build |
4aa2fb |
int chan_recv_int64(chan_t*, int64_t*);
|
|
rpm-build |
4aa2fb |
#if ULONG_MAX == 4294967295UL
|
|
rpm-build |
4aa2fb |
# define chan_recv_int(c, d) chan_recv_int64(c, d)
|
|
rpm-build |
4aa2fb |
#else
|
|
rpm-build |
4aa2fb |
# define chan_recv_int(c, d) chan_recv_int32(c, d)
|
|
rpm-build |
4aa2fb |
#endif
|
|
rpm-build |
4aa2fb |
int chan_recv_double(chan_t*, double*);
|
|
rpm-build |
4aa2fb |
int chan_recv_buf(chan_t*, void*, size_t);
|
|
rpm-build |
4aa2fb |
|
|
rpm-build |
4aa2fb |
#endif
|