facebookexperimental / libunifex

Unified Executors
Other
1.42k stars 182 forks source link

lock_guard and async_mutex interactions #440

Open GorNishanov opened 2 years ago

GorNishanov commented 2 years ago

I was wandering if awaiting on an async_mutex should return a reference to async_mutex, then, it could be used together with lock_guard and unique_lock nicely (at least for initial acquisition).

https://godbolt.org/z/eKvYzxzTn

struct async_mutex {
    async_mutex& async_lock() { return *this; }
    void unlock() { puts("unlocked"); }
};
#define CO_AWAIT

int main() {
    async_mutex mut;
    {
        std::lock_guard lock(CO_AWAIT mut.async_lock(), std::adopt_lock);
    }
    {
        std::unique_lock lock(CO_AWAIT mut.async_lock(), std::adopt_lock);
    }
}
janondrusek commented 2 years ago

Hi @GorNishanov! There was a proposal to enhance async_mutex in #387. Would the proposed pattern with sender algorithms suite your use case?

GorNishanov commented 2 years ago

If I understand https://github.com/facebookexperimental/libunifex/issues/387 correctly, it will make the usage to look like:

auto guard = co_await m.async_lock();

where the result of awaiting on async_lock will return a unique_lock/scope_guard like facility. Whereas, this proposal makes m.async_lock() to work with existing unique_lock/scope_guard.

I think from design perspective, the resolution proposed by this issue is simpler, does not need as much design and can be put into use sooner.

I think doing a proper design for https://github.com/facebookexperimental/libunifex/issues/387 will evolve into something like async_unique_lock that would allow dropping and re-aquiring lock and possibly an interaction with condition_variable and will take longer to get right.

Thus, I am thinking, do something like https://github.com/facebookexperimental/libunifex/issues/440 now and take time to evolve https://github.com/facebookexperimental/libunifex/issues/387 to its final form and add it when its ready. It is not in a conflict with this suggestion.