STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
Concurrency::reader_writer_lock Class Reference

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_lockoperator= (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
 

Detailed Description

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.

See also
critical_section Class

Constructor & Destructor Documentation

_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.

Concurrency::reader_writer_lock::reader_writer_lock ( const reader_writer_lock _Lock)
private

Hide copy constructor for a reader_writer_lock

Member Function Documentation

void Concurrency::reader_writer_lock::_Acquire_lock ( void _PLockingNode,
bool  _FHasExternalNode 
)

Acquires a write lock given a specific write node to lock.

Parameters
_PLockingNodeThe node that needs to own the lock.
_FHasExternalNodeAn 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.

void* Concurrency::reader_writer_lock::_Get_reader_convoy ( )
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.

Returns
Pointer to the head of the reader list.
void Concurrency::reader_writer_lock::_Remove_last_writer ( void _PWriter)
private

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.

Parameters
_PWriterLast writer in the queue.
bool Concurrency::reader_writer_lock::_Set_next_writer ( void _PWriter)
private

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.

Parameters
_PWriterThe first writer in the queue.
void Concurrency::reader_writer_lock::_Switch_to_active ( void _PWriter)
private

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.

Parameters
_PWriterThe writer that needs to own the lock.
void Concurrency::reader_writer_lock::_Unlock_reader ( )
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.

void Concurrency::reader_writer_lock::_Unlock_writer ( )
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.

See also
reader_writer_lock::unlock Method
_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.

See also
reader_writer_lock::unlock Method
reader_writer_lock& Concurrency::reader_writer_lock::operator= ( const reader_writer_lock _Lock)
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.

Returns
If the lock was acquired, the value true; otherwise, the value false.
See also
reader_writer_lock::unlock Method
_CONCRTIMP bool Concurrency::reader_writer_lock::try_lock_read ( )

Attempts to acquire the reader-writer lock as a reader without blocking.

Returns
If the lock was acquired, the value true; otherwise, the value false.
See also
reader_writer_lock::unlock Method
_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.

See also
reader_writer_lock::lock Method, reader_writer_lock::lock_read Method, reader_writer_lock::try_lock Method, reader_writer_lock::try_lock_read Method

Member Data Documentation

_CONCRT_BUFFER Concurrency::reader_writer_lock::_M_activeWriter[(4 *sizeof(void *)+2 *sizeof(unsigned int)+sizeof(_CONCRT_BUFFER)-1)/sizeof(_CONCRT_BUFFER)]
private
volatile long Concurrency::reader_writer_lock::_M_lockState
private
void* Concurrency::reader_writer_lock::_M_pReaderHead
private
void* Concurrency::reader_writer_lock::_M_pWriterHead
private
void* Concurrency::reader_writer_lock::_M_pWriterTail
private

The documentation for this class was generated from the following file: