template <typename F> 
auto operator|(F&& f)
(1)
template <typename F>
auto operator|(detail::annotated_process<F>&& ap)
(2)

Creates a new receiver, attaches the given process as downstream to it and returns this new receiver. The new receiver inherits the executor from its upstream receiver if not an alternative executor is attached. In case that T of receiver<T> is a move only type, repeated calls of this operator overwrite the previous attached downstream channel.

  1. Attaches the given process to the receiver and returns a new receiver. It can either be a function object with a single parameter or a process that has an await() and a yield() method.

  2. Attaches the given annotated process to the receiver and returns a new receiver. It can either be a function object with a single parameter or a process that follows this signature. An annotated_process should not be explicitly instantiated but it gets implicitly created as soon as one combines a function object with an operator& and an executor or a buffer_size or both.

Parameters

f

The process to be executed.

args

Futures that shall be joined

Return value

A receiver of type of the result of the passed function object

Example 1

#include <atomic>
#include <thread>
#include <stlab/concurrency/channel.hpp>
#include <stlab/concurrency/default_executor.hpp>
#include <stlab/concurrency/immediate_executor.hpp>

using namespace stlab;

int main() {
    sender<int> send;
    receiver<int> receive;

    std::tie(send, receive) = channel<int>(default_executor);

    std::atomic_int v{0};

    // The code demonstrates how a process can be annotated
    auto result = receive 
        | buffer_size{ 3 } & [](int x) { return x * 2; }
        | [](int x) { return x * 2; } & buffer_size{ 2 }
        | buffer_size{ 3 } & executor{ default_executor } & [](int x) { return x * 2; } 

        | executor{ default_executor } & [](int x) { return x + 1; }
        | [](int x) { return x + 1; } & executor{ immediate_executor }
        | executor{ default_executor } & buffer_size{ 3 } & [](int x) { return x * 2; }
    
        | [](int x) { return x + 1; } & executor{ default_executor } & buffer_size{ 3 }
        | [](int x) { return x * 2; } & buffer_size{ 3 } & executor{ immediate_executor }
        
        | [&v](int x) { v = x; };
        
    receive.set_ready();

    send(1);

    while (v == 0) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
}