MegaDrive
On this page

Structured Networking in C++ - CppCon 2022

A note of Dietmar Kühl's talk at CppCon2022.

Objective

To Integrate networking with the concurrency approach, and provide protable classes and functions.

The steps are:

  1. Decompose work into senders each representing work.
  2. Combine the work representation with a receiver.
  3. Start the resulting entity.

The Basic Non-Concurrency Toy Networking

struct immovable{ immovable() = default; immovable(immovable&&) = delete;}

class task
{
public:
    template<tyename S>
    struct awaiter
    {
        using ResultType = typename S::result_t;
        
        struct receiver {
            awaiter* a;
            friend void set_value(receiver self, auto v) {
                self.a->value_.emplace(std::move(v));
                self.a->handle_.resume();
            }
            friend void set_value(receiver self, auto e) {
                self.a->error_ = e;
                self.a->handle_.resume();
            }
        };

        awaiter(S s): state_(connect(s, reicever{this})) {}
        bool await_ready() {return false;}
        void await_suspend(std::coroutine_handle<void> handle) {
            this->handle_ = handle;
            start(state_);
        }

        ResultType await_resume() {
            if(error_) std::rethrow_exception(error);
            return std::move(*value);
        }

        using state_t = decltype(connect(std::declval<S>(), std::declval<receiver>()));

        std::coroutine_handle<void> handle_;
        state_t state_;
        std::optional<RusultType> value_;
        std::exception_ptr error_;
    };


    struct none {};
    using result_t = none;

    struct state_base: immovable {
        state_base() = default;
        state_base(state_base&&) = delete;
        virtual void complete() = 0;
    };

    struct promise_type: immovable
    {
        state_base* state = nullptr;
        
        task get_return_object() { 
            return {std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        
        std::suspend_always initial_suspend() {return {};}
        
        std::suspend_never final_suspend() noexcept {
            if(state) state->complete();
            return {};
        }
        
        void unhandled_exception() { std::terminate();}

    }


    
}