تنفيذ C النقي لقنوات GO.
توفر القنوات غير المخصصة آلية للتواصل وكذلك التزامن. عند إرسال البيانات إلى القناة ، يتم كتل المرسل حتى يصبح جهاز الاستقبال جاهزًا. وبالمثل ، سيتم حظر جهاز الاستقبال حتى يصبح المرسل جاهزًا.
#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 );
} مع قناة غير مجهزة ، تتم مزامنة المرسل والمستقبل ، لذلك سيقوم البرنامج أعلاه بطباعة ping .
تقبل القنوات المخزنة عددًا محدودًا من القيم بدون جهاز استقبال مماثل لتلك القيم. لن يحظر إرسال البيانات ما لم تكن القناة ممتلئة. سيتم حظر استلام البيانات فقط إذا كانت القناة فارغة.
#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 );
} سيقوم البرنامج أعلاه بطباعة buffered ثم channel . لا تحظر Sends لأن القناة لديها سعة 2. إرسال المزيد بعد ذلك سيحظر حتى تم استلام القيم.
عند إغلاق قناة ، لا يمكن إرسال أي قيم مزيد من القيم. سيؤدي الاستلام على قناة مغلقة إلى إرجاع رمز إشارة إلى أنه تم إغلاق القناة. قد يكون هذا مفيدًا لتوصيل إكمال مستقبلات القناة. إذا تم تخزين القناة المغلقة ، فسيتم استلام القيم عليها حتى فارغة.
#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 );
}سيطبع هذا البرنامج:
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
حدد عبارات اختر أي مجموعة من عمليات الإرسال أو الاستقبال الممكنة ستستمر. كما أنها توفر وسيلة لأداء الإرسالات غير المحظورة وتتلقى. تختار مفيدة بشكل خاص للاتصال بضاعفة على عدة قنوات.
#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 );
}سيطبع هذا البرنامج:
no message received
no message sent
no activity