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_interruptAPI 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();
};