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

[MathJax off]

7 Channels
7.1 Channels
7.1-1 CreateChannel
7.1-2 SendChannel
7.1-3 TransmitChannel
7.1-4 TrySendChannel
7.1-5 TryTransmitChannel
7.1-6 ReceiveChannel
7.1-7 TryReceiveChannel
7.1-8 MultiSendChannel
7.1-9 TryMultiSendChannel
7.1-10 MultiReceiveChannel
7.1-11 ReceiveAnyChannel
7.1-12 ReceiveAnyChannelWithIndex
7.1-13 TallyChannel
7.1-14 InspectChannel

### 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 of`ReceiveChannel` (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