Reine C -Implementierung von GO -Kanälen.
Ungepufferte Kanäle bieten sowohl einen Mechanismus für Kommunikation als auch Synchronisation. Wenn Daten in den Kanal gesendet werden, blockiert der Absender, bis ein Empfänger fertig ist. Ebenso blockiert ein Empfänger, bis ein Absender fertig ist.
#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 );
} Mit einem ausgefiebten Kanal werden der Absender und der Empfänger synchronisiert, sodass das obige Programm ping druckt.
Gepufferte Kanäle akzeptieren eine begrenzte Anzahl von Werten ohne einen entsprechenden Empfänger für diese Werte. Das Senden von Daten blockiert nicht, es sei denn, der Kanal ist voll. Das Empfangen von Daten blockiert nur, wenn der Kanal leer ist.
#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 );
} Das obige Programm druckt buffered und channel dann. Die Sendungen blockieren nicht, da der Kanal eine Kapazität von 2 hat. Wenn Sie nach diesem, was die Werte erhalten hatten, werden mehr gesendet.
Wenn ein Kanal geschlossen ist, können keine Werte mehr darauf gesendet werden. Das Empfangen auf einem geschlossenen Kanal gibt einen Indikationscode zurück, den der Kanal geschlossen wurde. Dies kann nützlich sein, um den Empfängern des Kanals die Fertigstellung zu vermitteln. Wenn der geschlossene Kanal gepuffert ist, werden Werte darauf empfangen, bis sie leer sind.
#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 );
}Dieses Programm druckt:
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
Wählen Sie Aussagen aus, welche von einer Reihe möglicher Sende- oder Empfangsvorgänge fortgesetzt werden. Sie bieten auch eine Möglichkeit, nicht blockierende Sendungen durchzuführen und zu empfangen. Ausgewählte sind besonders nützlich für die Multiplex -Kommunikation über mehrere Kanäle.
#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 );
}Dieses Programm druckt:
no message received
no message sent
no activity