Lock and Synchronization
Multiple coroutines in the same OS thread have no visibility issues with each other. For example, if multiple coroutines modify variables inside a thread at the same time, we don't need to use atomic variables, and there is no need to pay attention to memory order.
But sync primitives are still needed, because locks are needed to protect variables from being modified by other coroutines, if the lock owner might have a chance to yield its CPU.
All Photon's synchronization primitives are thead-safe, including the
thread_interrupt
API we introduced before.
Namespace
photon::
Headers
<photon/thread/thread.h>
API
mutex
class mutex {
public:
int lock(uint64_t timeout = -1); // threads are guaranteed to get the lock
int try_lock(); // in FIFO order, when there's contention
void unlock();
}
note
The timeout type is uint64_t
. -1UL means forever.
spinlock
class spinlock {
public:
int lock();
int try_lock();
void unlock();
};
scoped_lock
using scoped_lock = locker<mutex>;
condition_variable
class condition_variable {
public:
int wait(mutex* m, uint64_t timeout = -1);
int wait(mutex& m, uint64_t timeout = -1);
int wait(spinlock* m, uint64_t timeout = -1);
int wait(spinlock& m, uint64_t timeout = -1);
int wait(scoped_lock& lock, uint64_t timeout = -1);
int wait_no_lock(uint64_t timeout = -1);
thread* notify_one();
int notify_all();
};
semaphore
class semaphore {
public:
explicit semaphore(uint64_t count = 0);
int wait(uint64_t count, uint64_t timeout = -1);
int signal(uint64_t count);
uint64_t count() const;
};
rwlock
class rwlock {
public:
int lock(int mode, uint64_t timeout = -1); // mode: RLOCK / WLOCK
int unlock();
};