BitShares-Core
7.0.2
BitShares blockchain node software and command-line wallet software
|
mutex More...
#include <mutex.hpp>
Public Member Functions | |
mutex () | |
~mutex () | |
bool | try_lock () |
bool | try_lock_for (const microseconds &rel_time) |
bool | try_lock_until (const time_point &abs_time) |
void | lock () |
void | unlock () |
mutex
This mutex has an advantage over boost::mutex in that it does not involve any system calls, even in contention.
Uncontensted access is a simple compare and swap, no delay.
Contested access by different fibers in the same thread simply yields the thread until the lock is available. Actual delay is subject to the cooperative nature of other tasks in the fiber's thread.
Contested access by different threads requires a spin lock while the task is enqueued. Because the enqueue action is well-defined and 'short-lived' time spent 'spinning' should be minimal.
Cooperatively multi-tasked code must still worry about reentrancy. Suppose you have a thread sending a message across a socket, the socket members are thread safe, but the write_message()
operation is not rentrant because the context could yield while waiting for a partial write to complete.
If while it has yielded another task in the same thread attempts to write a second message then you will get garbage out as both fibers take turns writing parts of their messages out of the socket.
Example problem:
The output could look something like:
What you want to happen is this:
Now if while writing the first message, someone attempts to write a second message second write will 'queue' behind the first by 'blocking' on the mutex.
As a result we now have to extend the normal discussion on thread-safe vs reentrant.
In the example above, before we added the mutex the code was thread-unsafe After we added the mutex the code became coop-thread-safe, and potentially prempt-thread-safe
To be preempt-thread-safe any operations must be atomic or protected by a lock because the OS could switch you out between any two instructions.
To be coop-thread-safe all operations are 'atomic' unless they span a 'yield'. If they span a yield (such as writing parts of a message), then a mutex is required.
bool fc::mutex::try_lock | ( | ) |
bool fc::mutex::try_lock_for | ( | const microseconds & | rel_time | ) |
bool fc::mutex::try_lock_until | ( | const time_point & | abs_time | ) |