Skip to main content

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(Timeout timeout = {});
int try_lock();
void unlock();
}
note

The default value of Timeout is -1UL (microseconds), which means forever.

// For seq_mutex, threads are guaranteed to get the lock in FIFO order, when there's contention
class seq_mutex : public mutex {
};

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, Timeout timeout = {});
int wait(mutex& m, Timeout timeout = {});

int wait(spinlock* m, Timeout timeout = {});
int wait(spinlock& m, Timeout timeout = {});

int wait(scoped_lock& lock, Timeout timeout = {});
int wait_no_lock(Timeout timeout = {});

thread* notify_one();
int notify_all();
};

semaphore

class semaphore {
public:
explicit semaphore(uint64_t count = 0);
/**
* @brief A wrapper of wait that cannot be interrupted
*/
int wait(uint64_t count, Timeout timeout = {});
/**
* @brief Subtract count.
* @return 1) Count is successfully subtracted (might have been waited). Returns 0.
* 2) Count is not enough until timeout. Returns -1, errno is set to ETIMEDOUT.
* 3) Interrupted by another thread before timeout. Returns -1, errno is decided by the interrupter.
*/
int wait_interruptible(uint64_t count, Timeout timeout = {});
/**
* @brief Add count. Does not require Photon environment, can be invoked in any std thread.
*/
int signal(uint64_t count);
uint64_t count() const;
};

rwlock

class rwlock {
public:
int lock(int mode, Timeout timeout = {}); // mode: RLOCK / WLOCK
int unlock();
};