STLdoc
STLdocumentation
|
A writer-preference queue-based reader-writer lock with local only spinning. The lock grants first in - first out (FIFO) access to writers and starves readers under a continuous load of writers. More...
#include <concrt.h>
Classes | |
class | scoped_lock |
An exception safe RAII wrapper that can be used to acquire reader_writer_lock lock objects as a writer. More... | |
class | scoped_lock_read |
An exception safe RAII wrapper that can be used to acquire reader_writer_lock lock objects as a reader. More... | |
Public Member Functions | |
_CONCRTIMP | reader_writer_lock () |
Constructs a new reader_writer_lock object. More... | |
_CONCRTIMP | ~reader_writer_lock () |
Destroys the reader_writer_lock object. More... | |
_CONCRTIMP void | lock () |
Acquires the reader-writer lock as a writer. More... | |
_CONCRTIMP bool | try_lock () |
Attempts to acquire the reader-writer lock as a writer without blocking. More... | |
_CONCRTIMP void | lock_read () |
Acquires the reader-writer lock as a reader. If there are writers, active readers have to wait until they are done. The reader simply registers an interest in the lock and waits for writers to release it. More... | |
_CONCRTIMP bool | try_lock_read () |
Attempts to acquire the reader-writer lock as a reader without blocking. More... | |
_CONCRTIMP void | unlock () |
Unlocks the reader-writer lock based on who locked it, reader or writer. More... | |
void | _Acquire_lock (void *_PLockingNode, bool _FHasExternalNode) |
Acquires a write lock given a specific write node to lock. More... | |
Private Member Functions | |
bool | _Set_next_writer (void *_PWriter) |
Called for the first context in the writer queue. It sets the queue head and it tries to claim the lock if readers are not active. More... | |
void * | _Get_reader_convoy () |
Called when writers are done with the lock, or when lock was free for claiming by the first reader coming in. If in the meantime there are more writers interested the list of readers is finalized and they are convoyed, while head of the list is reset to NULL. More... | |
void | _Unlock_writer () |
Called from unlock() when a writer is holding the lock. Writer unblocks the next writer in the list and is being retired. If there are no more writers, but there are readers interested, then readers are unblocked. More... | |
void | _Unlock_reader () |
Called from unlock() when a reader is holding the lock. Reader count is decremented and if this is the last reader it checks whether there are interested writers that need to be unblocked. More... | |
void | _Remove_last_writer (void *_PWriter) |
When the last writer leaves the lock, it needs to reset the tail to NULL so that the next coming writer would know to try to grab the lock. If the CAS to NULL fails, then some other writer managed to grab the tail before the reset, so this writer needs to wait until the link to the next writer is complete before trying to release the next writer. More... | |
void | _Switch_to_active (void *_PWriter) |
The writer node allocated on the stack never really owns the lock because it would go out of scope and the insides would not be visible in unlock() where it could potentially need to unblock the next writer in the queue. Instead, its state is transferred to the internal writer node which is used as a scratch node. More... | |
reader_writer_lock (const reader_writer_lock &_Lock) | |
Hide copy constructor for a reader_writer_lock More... | |
reader_writer_lock & | operator= (const reader_writer_lock &_Lock) |
Hide assignment operator for a reader_writer_lock More... | |
Private Attributes | |
_CONCRT_BUFFER | _M_activeWriter [(4 *sizeof(void *)+2 *sizeof(unsigned int)+sizeof(_CONCRT_BUFFER)-1)/sizeof(_CONCRT_BUFFER)] |
void * | _M_pReaderHead |
void * | _M_pWriterHead |
void * | _M_pWriterTail |
volatile long | _M_lockState |
A writer-preference queue-based reader-writer lock with local only spinning. The lock grants first in - first out (FIFO) access to writers and starves readers under a continuous load of writers.
For more information, see Synchronization Data Structures.
_CONCRTIMP Concurrency::reader_writer_lock::reader_writer_lock | ( | ) |
Constructs a new reader_writer_lock
object.
_CONCRTIMP Concurrency::reader_writer_lock::~reader_writer_lock | ( | ) |
Destroys the reader_writer_lock
object.
It is expected that the lock is no longer held when the destructor runs. Allowing the reader writer lock to destruct with the lock still held results in undefined behavior.
|
private |
Hide copy constructor for a reader_writer_lock
void Concurrency::reader_writer_lock::_Acquire_lock | ( | void * | _PLockingNode, |
bool | _FHasExternalNode | ||
) |
Acquires a write lock given a specific write node to lock.
_PLockingNode | The node that needs to own the lock. |
_FHasExternalNode | An indication if the node being locked is external to the reader_writer_lock object. |
If the lock is already held by the calling context, an .improper_lock exception will be thrown.
|
private |
Called when writers are done with the lock, or when lock was free for claiming by the first reader coming in. If in the meantime there are more writers interested the list of readers is finalized and they are convoyed, while head of the list is reset to NULL.
When the last writer leaves the lock, it needs to reset the tail to NULL so that the next coming writer would know to try to grab the lock. If the CAS to NULL fails, then some other writer managed to grab the tail before the reset, so this writer needs to wait until the link to the next writer is complete before trying to release the next writer.
_PWriter | Last writer in the queue. |
Called for the first context in the writer queue. It sets the queue head and it tries to claim the lock if readers are not active.
_PWriter | The first writer in the queue. |
The writer node allocated on the stack never really owns the lock because it would go out of scope and the insides would not be visible in unlock() where it could potentially need to unblock the next writer in the queue. Instead, its state is transferred to the internal writer node which is used as a scratch node.
_PWriter | The writer that needs to own the lock. |
|
private |
Called from unlock() when a reader is holding the lock. Reader count is decremented and if this is the last reader it checks whether there are interested writers that need to be unblocked.
|
private |
Called from unlock() when a writer is holding the lock. Writer unblocks the next writer in the list and is being retired. If there are no more writers, but there are readers interested, then readers are unblocked.
_CONCRTIMP void Concurrency::reader_writer_lock::lock | ( | ) |
Acquires the reader-writer lock as a writer.
It is often safer to utilize the scoped_lock construct to acquire and release a reader_writer_lock
object as a writer in an exception safe way.
After a writer attempts to acquire the lock, any future readers will block until the writers have successfully acquired and released the lock. This lock is biased towards writers and can starve readers under a continuous load of writers.
Writers are chained so that a writer exiting the lock releases the next writer in line.
If the lock is already held by the calling context, an improper_lock exception will be thrown.
_CONCRTIMP void Concurrency::reader_writer_lock::lock_read | ( | ) |
Acquires the reader-writer lock as a reader. If there are writers, active readers have to wait until they are done. The reader simply registers an interest in the lock and waits for writers to release it.
It is often safer to utilize the scoped_lock_read construct to acquire and release a reader_writer_lock
object as a reader in an exception safe way.
If there are writers waiting on the lock, the reader will wait until all writers in line have acquired and released the lock. This lock is biased towards writers and can starve readers under a continuous load of writers.
|
private |
Hide assignment operator for a reader_writer_lock
_CONCRTIMP bool Concurrency::reader_writer_lock::try_lock | ( | ) |
Attempts to acquire the reader-writer lock as a writer without blocking.
true
; otherwise, the value false
. _CONCRTIMP bool Concurrency::reader_writer_lock::try_lock_read | ( | ) |
Attempts to acquire the reader-writer lock as a reader without blocking.
true
; otherwise, the value false
. _CONCRTIMP void Concurrency::reader_writer_lock::unlock | ( | ) |
Unlocks the reader-writer lock based on who locked it, reader or writer.
If there are writers waiting on the lock, the release of the lock will always go to the next writer in FIFO order. This lock is biased towards writers and can starve readers under a continuous load of writers.
|
private |
|
private |
|
private |
|
private |
|
private |