Is there any specification on c++20 coroutine with std::mutex

Viewed 61

Does C++20 coroutine have any specification on coroutine with std::mutex? Is it problematic to use std::mutex in a coroutine? If it is, is there any solution?

The following are 3 examples (I'm quite new to a coroutine, correct me if I'm wrong).

Example 1: coroutine with std::mutex and blocking operation

In a coroutine, we need to do a blocking operation with a lock, so that no multiple coroutines do the job at the same time.

task<> with_mutex_and_blocking_op() {
    Result result;
    {
        std::lock_guard<std::mutex> lock(some_non_recursive_mutex);  // ensure there's only one coroutine calls `call_blocking_io`

        result = call_blocking_io();   // block here until IO finishes
    }

    co_await some_awaiter(result);
}

Example 2: coroutine with std::mutex

We can start an async operation in await_suspend, and get its result in await_resume. The async operation submits a task to a task queue, and the queue is protected by a std::mutex, or gets some lock-protected resources for the async operation.

void await_suspend(std::coroutine_handle<> handle) {
    auto task = create_an_async_task();

    std::lock_guard<std::mutex> lock(some_non_recursive_mutex);

    task_queue.push(std::move(task));
}

Example 3: coroutine with std::mutex protecting a co_await

This is a similar problem with Example 1, except that the critical section calls co_await.

Some ideas

Example 1 seems like an anti-pattern, i.e. calling a blocking function in a coroutine, but I'm wondering what will happen? Say coroutine A acquires the mutex and calls call_blocking_io. Since it's blocking, I think the scheduler will switch to another coroutine, e.g. coroutine B. Unfortunately, B is scheduled on the same thread as coroutine A and tries to lock the mutex. This results in the same thread trying to lock the non-recursive mutex twice, and its undefined behavior.

Example 2 tries to lock the mutex in await_suspend. If it cannot acquire the lock, it will block. In this case, does the scheduler switch to another coroutine? If it will be switched, I think it has the same problem as Example 1.

Example 3 already has an answer and a solution. I'm wondering, 4 years passed if it's still the case? Does C++ 20 release some feature to solve it?

0 Answers
Related