Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

7 Channels
 7.1 Channels

7 Channels

7.1 Channels

Channels are FIFO queues that threads can use to coordinate their activities.

7.1-1 CreateChannel
‣ CreateChannel( [capacity] )( function )

CreateChannel returns a FIFO communication channel that can be used to exchange information between threads. Its optional argument is a capacity (positive integer). If insufficient resources are available to create a channel, it returns -1. If the capacity is not a positive integer, an error will be raised.

If a capacity is not provided, by default the channel can hold an indefinite number of objects. Otherwise, attempts to store objects in the channel beyond its capacity will block.

gap> ch1:=CreateChannel();
<channel 0x460339c: 0 elements, 0 waiting>
gap> ch2:=CreateChannel(5);
<channel 0x460324c: 0/5 elements, 0 waiting>

7.1-2 SendChannel
‣ SendChannel( channel, obj )( function )

SendChannel accepts two arguments, a channel object returned by CreateChannel (7.1-1), and an arbitrary GAP object. It stores obj in channel. If channel has a finite capacity and is currently full, then SendChannel will block until at least one element has been removed from the channel, e.g. using ReceiveChannel (7.1-6).

SendChannel performs automatic region migration for thread-local objects. If obj is thread-local for the current thread, it will be migrated (along with all subobjects contained in the same region) to the receiving thread's thread-local data space. In between sending and receiving, obj cannot be accessed by either thread.

This example demonstrates sending messages across a channel.

gap> ch1 := CreateChannel();;
gap> SendChannel(ch1,1);
gap> ch1;
<channel 0x460339c: 1 elements, 0 waiting>
gap> ReceiveChannel(ch1);
1
gap> ch1;
<channel 0x460339c: 0 elements, 0 waiting>

Sleep in the following example is used to demonstrate blocking.

gap> ch2 := CreateChannel(5);;
gap> ch3 := CreateChannel();;
gap> for i in [1..5] do SendChannel(ch2,i); od;
gap> ch2;
<channel 0x460324c: 5/5 elements, 0 waiting>
gap> t:=CreateThread(
> function()
> local x;
> Sleep(10);
> x:=ReceiveChannel(ch2);
> Sleep(10);
> SendChannel(ch3,x);
> Print("Thread finished\n");
> end);;
> SendChannel(ch2,3); # this blocks until the thread reads from ch2
gap> ReceiveChannel(ch3); # the thread is blocked until we read from ch3
1
Thread finished
gap> WaitThread(t);

7.1-3 TransmitChannel
‣ TransmitChannel( channel, obj )( function )

TransmitChannel is identical to SendChannel (7.1-2), except that it does not perform automatic region migration of thread-local objects.

gap> ch := CreateChannel(5);;
gap> l := [ 1, 2, 3];;
gap> original_region := RegionOf(l);;
gap> SendChannel(ch, l);
gap> WaitThread(CreateThread(function()
>      local ob; ob := ReceiveChannel(ch);
>      Display(RegionOf(ob) = original_region);
>    end));
false
gap> l := [ 1, 2, 3];;
gap> original_region := RegionOf(l);;
gap> TransmitChannel(ch, l);
gap> WaitThread(CreateThread(function()
>      local ob; ob := ReceiveChannel(ch);
>      Display(RegionOf(ob) = original_region);
>    end));
true

7.1-4 TrySendChannel
‣ TrySendChannel( channel, obj )( function )

TrySendChannel is identical to SendChannel (7.1-2), except that it returns if the channel is full instead of blocking. It returns true if the send was successful and false otherwise.

gap> ch := CreateChannel(1);;
gap> TrySendChannel(ch, 99);
true
gap> TrySendChannel(ch, 99);
false

7.1-5 TryTransmitChannel
‣ TryTransmitChannel( channel, obj )( function )

TryTransmitChannel is identical to TrySendChannel (7.1-4), except that it does not perform automatic region migration of thread-local objects.

7.1-6 ReceiveChannel
‣ ReceiveChannel( channel )( function )

ReceiveChannel is used to retrieve elements from a channel. If channel is empty, the call will block until an element has been added to the channel via SendChannel (7.1-2) or a similar primitive.

See SendChannel (7.1-2) for an example.

7.1-7 TryReceiveChannel
‣ TryReceiveChannel( channel, default )( function )

TryReceiveChannel, like ReceiveChannel (7.1-6), attempts to retrieve an object from channel. If it does not succeed, however, it will return default rather than blocking.

gap> ch := CreateChannel();;
gap> SendChannel(ch, 99);
gap> TryReceiveChannel(ch, fail);
99
gap> TryReceiveChannel(ch, fail);
fail

7.1-8 MultiSendChannel
‣ MultiSendChannel( channel, list )( function )

MultiSendChannel allows the sending of all the objects contained in the list list to channel as a single operation. The list must be dense and is not modified by the call. The function will send elements starting at index 1 until all elements have been sent. If a channel with finite capacity is full, then the operation will block until all elements can be sent.

The operation is designed to be more efficient than sending all elements individually via SendChannel (7.1-2) by minimizing potentially expensive concurrency operations.

See MultiReceiveChannel (7.1-10) for an example.

7.1-9 TryMultiSendChannel
‣ TryMultiSendChannel( channel, list )( function )

TryMultiSendChannel operates like MultiSendChannel (7.1-8), except that it returns rather than blocking if it cannot send any more elements if the channel is full. It returns the number of elements it has sent. If channel does not have finite capacity, TryMultiSendChannel will always send all elements in the list.

7.1-10 MultiReceiveChannel
‣ MultiReceiveChannel( channel, amount )( function )

MultiReceiveChannel is the receiving counterpart to MultiSendChannel (7.1-8).It will try to receive up to amount objects from channel. If the channel contains less than amount objects, it will return rather than blocking.

The function returns a list of all the objects received.

gap> ch:=CreateChannel();;
gap> MultiSendChannel(ch, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
gap> MultiReceiveChannel(ch,7);
[ 1, 2, 3, 4, 5, 6, 7 ]
gap> MultiReceiveChannel(ch,7);
[ 8, 9, 10 ]
gap> MultiReceiveChannel(ch,7);
[  ]

7.1-11 ReceiveAnyChannel
‣ ReceiveAnyChannel( channel_1, ..., channel_n )( function )
‣ ReceiveAnyChannel( channel_list )( function )

ReceiveAnyChannel is a multiplexing variant ofReceiveChannel (7.1-6). It blocks until at least one of the channels provided contains an object. It will then retrieve that object from the channel and return it.

gap> ch1 := CreateChannel();;
gap> ch2 := CreateChannel();;
gap> SendChannel(ch2, [1, 2, 3]);;
gap> ReceiveAnyChannel(ch1, ch2);
[ 1, 2, 3 ]

7.1-12 ReceiveAnyChannelWithIndex
‣ ReceiveAnyChannelWithIndex( channel_1, ..., channel_n )( function )
‣ ReceiveAnyChannelWithIndex( channel_list )( function )

ReceiveAnyChannelWithIndex works like ReceiveAnyChannel (7.1-11), except that it returns a list with two elements, the first being the object being received, the second being the number of the channel from which the object has been retrieved.

gap> ch1 := CreateChannel();;
gap> ch2 := CreateChannel();;
gap> SendChannel(ch2, [1, 2, 3]);;
gap> ReceiveAnyChannelWithIndex(ch1, ch2);
[ [ 1, 2, 3 ], 2 ]

7.1-13 TallyChannel
‣ TallyChannel( channel )( function )

TallyChannel returns the number of objects that a channel contains. This number can increase or decrease, as data is sent to or received from this channel. Send operations will only ever increase and receive operations will only ever decrease this count. Thus, if there is only one thread receiving data from the channel, it can use the result as a lower bound for the number of elements that will be available in the channel.

gap> ch := CreateChannel();;
gap> SendChannel(ch, 2);
gap> SendChannel(ch, 3);
gap> SendChannel(ch, 5);
gap> TallyChannel(ch);
3

7.1-14 InspectChannel
‣ InspectChannel( channel )( function )

InspectChannel returns a list of the objects that a channel contains. Note that objects that are not in the shared, public, or read-only region will be temporarily stored in the so-called limbo region while in transit and will be inaccessible through normal means until they have been received.

gap> ch := CreateChannel();;
gap> SendChannel(ch, 2);
gap> SendChannel(ch, 3);
gap> SendChannel(ch, 5);
gap> InspectChannel(ch);
[ 2, 3, 5 ]

This function is primarily intended for debugging purposes.

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 Ind

generated by GAPDoc2HTML