Remix.run Logo
gpderetta 12 hours ago

You can go full circle and also make operations on a mutex asynchronous. Hence the realization that message passing and shared memory are truly dual.

mgaunard 11 hours ago | parent [-]

The very idea of a mutex is that it is synchronous. You wait until you can acquire the mutex.

If it's asynchronous, it's not a mutex anymore, or it's just used to synchronously setup some other asynchronous mechanism.

gpderetta 10 hours ago | parent [-]

A mutex is a way to guarantee mutual exclusion nothing more nothing less; You can recover synchronous behaviour if you really want:

    synchronized<Something> something;
    ...
    co_await something.async_visit([&](Something& x) {
        /* critical section here */ 
    });
mgaunard 10 hours ago | parent [-]

that isn't a mutex, that's delegating work asynchronously and delegating something else to run when it is complete (the implicitly defined continuation through coroutines).

In systems programming parlance, a mutex is a resource which can be acquired and released, acquired exactly once, and blocks on acquire if already acquired.

gpderetta 10 hours ago | parent [-]

Do a CPS transform of your typical std::mutex critical section and you'll find they are exactly the same.

mgaunard 9 hours ago | parent [-]

They're not, the interactions with the memory model are different, as are the guarantees.

CPS shouldn't be able to deadlock for example?

gpderetta 9 hours ago | parent [-]

CPS can trivially deadlock for all meaningful definitions of deadlock.

Would you consider this a mutex?

   async_mutex mux;

   co_await mux.lock();
   /* critical section */
   co_await mux.unlock();
   
What about: my_mutex mux;

   {
      std::lock_guard _{mux};
      /* critical section */
   }
where the code runs in a user space fiber.

Would you consider boost synchronized a mutex?

Don't confuse the semantics with the implementation details (yes async/await leaks implementation details).