Implémentation pure C des canaux GO.
Les canaux non frappés fournissent à la fois un mécanisme de communication et de synchronisation. Lorsque les données sont envoyées dans le canal, l'expéditeur bloque jusqu'à ce qu'un récepteur soit prêt. De même, un récepteur se bloque jusqu'à ce qu'un expéditeur soit prêt.
#include <pthread.h>
#include <stdio.h>
#include "chan.h"
chan_t * chan ;
void * ping ()
{
// Send blocks until receiver is ready.
chan_send ( chan , "ping" );
return NULL ;
}
int main ()
{
// Initialize unbuffered channel.
chan = chan_init ( 0 );
pthread_t th ;
pthread_create ( & th , NULL , ping , NULL );
// Receive blocks until sender is ready.
void * msg ;
chan_recv ( chan , & msg );
printf ( "%sn" , msg );
// Clean up channel.
chan_dispose ( chan );
} Avec un canal non frappé, l'expéditeur et le récepteur sont synchronisés, de sorte que le programme ci-dessus imprimera ping .
Les canaux tamponnés acceptent un nombre limité de valeurs sans récepteur correspondant pour ces valeurs. L'envoi de données ne bloquera que si le canal est plein. La réception des données ne bloquera que si le canal est vide.
#include <stdio.h>
#include "chan.h"
int main ()
{
// Initialize buffered channel with a capacity of 2.
chan_t * chan = chan_init ( 2 );
// Send up to 2 values without receiver.
chan_send ( chan , "buffered" );
chan_send ( chan , "channel" );
// Later receive the values.
void * msg ;
chan_recv ( chan , & msg );
printf ( "%sn" , msg );
chan_recv ( chan , & msg );
printf ( "%sn" , msg );
// Clean up channel.
chan_dispose ( chan );
} Le programme ci-dessus imprimera buffered puis channel . Les envois ne bloquent pas car le canal a une capacité de 2. Envoi plus après cela, il serait bloqué jusqu'à ce que les valeurs soient reçues.
Lorsqu'un canal est fermé, aucune valeur ne peut être envoyée dessus. La réception sur un canal fermé renverra un code d'indication selon lequel le canal a été fermé. Cela peut être utile pour communiquer l'achèvement aux récepteurs du canal. Si le canal fermé est tamponné, des valeurs seront reçues jusqu'à ce qu'elles soient vides.
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include "chan.h"
chan_t * jobs ;
chan_t * done ;
void * worker ()
{
// Process jobs until channel is closed.
void * job ;
while ( chan_recv ( jobs , & job ) == 0 )
{
printf ( "received job %dn" , ( int ) job );
}
// Notify that all jobs were received.
printf ( "received all jobsn" );
chan_send ( done , "1" );
return NULL ;
}
int main ()
{
// Initialize channels.
jobs = chan_init ( 5 );
done = chan_init ( 0 );
pthread_t th ;
pthread_create ( & th , NULL , worker , NULL );
// Send 3 jobs over the jobs channel then close it.
int i ;
for ( i = 1 ; i <= 3 ; i ++ )
{
chan_send ( jobs , ( void * ) ( uintptr_t ) i );
printf ( "sent job %dn" , i );
}
chan_close ( jobs );
printf ( "sent all jobsn" );
// Wait for all jobs to be received.
chan_recv ( done , NULL );
// Clean up channels.
chan_dispose ( jobs );
chan_dispose ( done );
}Ce programme imprimera:
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
Sélectionnez les instructions Choisissez lequel d'un ensemble d'opérations d'envoi ou de réception possibles se déroulera. Ils fournissent également un moyen d'effectuer des envois et des réceptions non bloquants. Les sélections sont particulièrement utiles pour le multiplexage de la communication sur plusieurs canaux.
#include <stdio.h>
#include "chan.h"
chan_t * messages ;
chan_t * signals ;
int main ()
{
// Initialize channels.
messages = chan_init ( 0 );
signals = chan_init ( 0 );
void * msg ;
// This is a non-blocking receive. If a value is available on messages,
// select will take the messages (0) case with that value. If not, it will
// immediately take the default case.
switch ( chan_select ( & messages , 1 , & msg , NULL , 0 , NULL ))
{
case 0 :
printf ( "received message %sn" , msg );
break ;
default :
printf ( "no message receivedn" );
}
// A non-blocking send works similarly.
msg = "foo" ;
switch ( chan_select ( NULL , 0 , NULL , & messages , 1 , & msg ))
{
case 0 :
printf ( "sent message %sn" , msg );
break ;
default :
printf ( "no message sentn" );
}
// We can use multiple cases above the default clause to implement a
// multi-way non-blocking select. Here we attempt non-blocking receives on
// both messages and signals.
chan_t * chans [ 2 ] = { messages , signals };
switch ( chan_select ( chans , 2 , & msg , NULL , 0 , NULL ))
{
case 0 :
printf ( "received message %sn" , msg );
break ;
case 1 :
printf ( "received signal %sn" , msg );
break ;
default :
printf ( "no activityn" );
}
// Clean up channels.
chan_dispose ( messages );
chan_dispose ( signals );
}Ce programme imprimera:
no message received
no message sent
no activity