Non Blocking Channel Operations in C
Our example demonstrates non-blocking channel operations using a select
statement with a default
clause. In C, we don’t have built-in channels or select statements, so we’ll simulate this behavior using pthreads and condition variables.
#include <stdio.h>
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#define MAX_MSG_LEN 256
typedef struct {
char message[MAX_MSG_LEN];
bool has_message;
pthread_mutex_t mutex;
pthread_cond_t cond;
} channel_t;
void channel_init(channel_t *ch) {
ch->has_message = false;
pthread_mutex_init(&ch->mutex, NULL);
pthread_cond_init(&ch->cond, NULL);
}
bool channel_try_receive(channel_t *ch, char *msg) {
bool received = false;
pthread_mutex_lock(&ch->mutex);
if (ch->has_message) {
strcpy(msg, ch->message);
ch->has_message = false;
received = true;
}
pthread_mutex_unlock(&ch->mutex);
return received;
}
bool channel_try_send(channel_t *ch, const char *msg) {
bool sent = false;
pthread_mutex_lock(&ch->mutex);
if (!ch->has_message) {
strcpy(ch->message, msg);
ch->has_message = true;
sent = true;
pthread_cond_signal(&ch->cond);
}
pthread_mutex_unlock(&ch->mutex);
return sent;
}
int main() {
channel_t messages, signals;
channel_init(&messages);
channel_init(&signals);
// Non-blocking receive
char msg[MAX_MSG_LEN];
if (channel_try_receive(&messages, msg)) {
printf("received message %s\n", msg);
} else {
printf("no message received\n");
}
// Non-blocking send
const char *hi = "hi";
if (channel_try_send(&messages, hi)) {
printf("sent message %s\n", hi);
} else {
printf("no message sent\n");
}
// Multi-way non-blocking select
if (channel_try_receive(&messages, msg)) {
printf("received message %s\n", msg);
} else if (channel_try_receive(&signals, msg)) {
printf("received signal %s\n", msg);
} else {
printf("no activity\n");
}
return 0;
}
This C program simulates non-blocking channel operations using a custom channel_t
struct and associated functions. Here’s how it works:
We define a
channel_t
struct that includes a message, a flag indicating if a message is present, a mutex for thread safety, and a condition variable for signaling.The
channel_init
function initializes a channel.channel_try_receive
attempts to receive a message from a channel without blocking. If a message is available, it returns true and copies the message.channel_try_send
attempts to send a message to a channel without blocking. If the channel is empty, it sends the message and returns true.In the
main
function, we create two channels:messages
andsignals
.We perform a non-blocking receive on the
messages
channel. If no message is available, it prints “no message received”.We attempt a non-blocking send of “hi” to the
messages
channel. Since the channel is empty, this should succeed.Finally, we simulate a multi-way non-blocking select by trying to receive from both
messages
andsignals
channels. If neither has a message, it prints “no activity”.
To compile and run this program:
$ gcc -o non_blocking_channels non_blocking_channels.c -lpthread
$ ./non_blocking_channels
no message received
sent message hi
received message hi
This example demonstrates how to implement non-blocking operations in C, which can be useful in scenarios where you want to check for data without getting stuck waiting.