Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
tbb::interface5::reader_writer_lock Class Reference

Writer-preference reader-writer lock with local-only spinning on readers. More...

#include <reader_writer_lock.h>

Inheritance diagram for tbb::interface5::reader_writer_lock:
Collaboration diagram for tbb::interface5::reader_writer_lock:

Classes

class  scoped_lock
 The scoped lock pattern for write locks. More...
 
class  scoped_lock_read
 The scoped lock pattern for read locks. More...
 

Public Types

enum  status_t { waiting_nonblocking, waiting, active, invalid }
 Status type for nodes associated with lock instances. More...
 

Public Member Functions

 reader_writer_lock ()
 Constructs a new reader_writer_lock. More...
 
 ~reader_writer_lock ()
 Destructs a reader_writer_lock object. More...
 
void __TBB_EXPORTED_METHOD lock ()
 Acquires the reader_writer_lock for write. More...
 
bool __TBB_EXPORTED_METHOD try_lock ()
 Tries to acquire the reader_writer_lock for write. More...
 
void __TBB_EXPORTED_METHOD lock_read ()
 Acquires the reader_writer_lock for read. More...
 
bool __TBB_EXPORTED_METHOD try_lock_read ()
 Tries to acquire the reader_writer_lock for read. More...
 
void __TBB_EXPORTED_METHOD unlock ()
 Releases the reader_writer_lock. More...
 

Private Member Functions

void __TBB_EXPORTED_METHOD internal_construct ()
 
void __TBB_EXPORTED_METHOD internal_destroy ()
 
bool start_write (scoped_lock *)
 Attempts to acquire write lock. More...
 
void set_next_writer (scoped_lock *w)
 Sets writer_head to w and attempts to unblock. More...
 
void end_write (scoped_lock *)
 Relinquishes write lock to next waiting writer or group of readers. More...
 
bool is_current_writer ()
 Checks if current thread holds write lock. More...
 
void start_read (scoped_lock_read *)
 Attempts to acquire read lock. More...
 
void unblock_readers ()
 Unblocks pending readers. More...
 
void end_read ()
 Relinquishes read lock by decrementing counter; last reader wakes pending writer. More...
 
- Private Member Functions inherited from tbb::internal::no_copy
 no_copy ()
 Allow default construction. More...
 

Private Attributes

atomic< scoped_lock_read * > reader_head
 The list of pending readers. More...
 
atomic< scoped_lock * > writer_head
 The list of pending writers. More...
 
atomic< scoped_lock * > writer_tail
 The last node in the list of pending writers. More...
 
tbb_thread::id my_current_writer
 Writer that owns the mutex; tbb_thread::id() otherwise. More...
 
atomic< uintptr_t > rdr_count_and_flags
 Status of mutex. More...
 

Friends

class scoped_lock
 
class scoped_lock_read
 

Detailed Description

Writer-preference reader-writer lock with local-only spinning on readers.

Loosely adapted from Mellor-Crummey and Scott pseudocode at http://www.cs.rochester.edu/research/synchronization/pseudocode/rw.html#s_wp

Definition at line 30 of file reader_writer_lock.h.

Member Enumeration Documentation

◆ status_t

Status type for nodes associated with lock instances.

waiting_nonblocking: the wait state for nonblocking lock instances; for writes, these transition straight to active states; for reads, these are unused.

waiting: the start and spin state for all lock instances; these will transition to active state when appropriate. Non-blocking write locks transition from this state to waiting_nonblocking immediately.

active: the active state means that the lock instance holds the lock; it will transition to invalid state during node deletion

invalid: the end state for all nodes; this is set in the destructor so if we encounter this state, we are looking at memory that has already been freed

The state diagrams below describe the status transitions. Single arrows indicate that the thread that owns the node is responsible for the transition; double arrows indicate that any thread could make the transition.

State diagram for scoped_lock status:

waiting -------—> waiting_nonblocking | _____________/ | V V V active --------------—> invalid

State diagram for scoped_lock_read status:

waiting | V active --------------—>invalid

Enumerator
waiting_nonblocking 
waiting 
active 
invalid 

Definition at line 70 of file reader_writer_lock.h.

Constructor & Destructor Documentation

◆ reader_writer_lock()

tbb::interface5::reader_writer_lock::reader_writer_lock ( )
inline

Constructs a new reader_writer_lock.

Definition at line 73 of file reader_writer_lock.h.

References internal_construct().

73  {
75  }
void __TBB_EXPORTED_METHOD internal_construct()
Here is the call graph for this function:

◆ ~reader_writer_lock()

tbb::interface5::reader_writer_lock::~reader_writer_lock ( )
inline

Destructs a reader_writer_lock object.

Definition at line 78 of file reader_writer_lock.h.

References internal_destroy().

78  {
80  }
void __TBB_EXPORTED_METHOD internal_destroy()
Here is the call graph for this function:

Member Function Documentation

◆ end_read()

void tbb::interface5::reader_writer_lock::end_read ( )
private

Relinquishes read lock by decrementing counter; last reader wakes pending writer.

Definition at line 282 of file reader_writer_lock.cpp.

References __TBB_ASSERT, ITT_NOTIFY, tbb::interface5::RC_INCR, rdr_count_and_flags, and sync_releasing.

Referenced by unlock().

282  {
283  ITT_NOTIFY(sync_releasing, this);
284  __TBB_ASSERT(rdr_count_and_flags >= RC_INCR, "unlock() called but no readers hold the lock.");
286 }
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
const uintptr_t RC_INCR
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:116
Here is the caller graph for this function:

◆ end_write()

void tbb::interface5::reader_writer_lock::end_write ( scoped_lock I)
private

Relinquishes write lock to next waiting writer or group of readers.

Definition at line 260 of file reader_writer_lock.cpp.

References __TBB_ASSERT, active, tbb::interface5::fetch_and_and(), id, ITT_NOTIFY, my_current_writer, tbb::interface5::reader_writer_lock::scoped_lock::next, rdr_count_and_flags, set_next_writer(), tbb::internal::spin_wait_while_eq(), sync_releasing, unblock_readers(), writer_head, and writer_tail.

Referenced by unlock().

260  {
261  __TBB_ASSERT(I==writer_head, "Internal error: can't unlock a thread that is not holding the lock.");
263  ITT_NOTIFY(sync_releasing, this);
264  if (I->next) { // potentially more writers
265  writer_head = I->next;
266  writer_head->status = active;
267  }
268  else { // No more writers; clear writer flag, test reader interest flag
269  __TBB_ASSERT(writer_head, NULL);
271  unblock_readers();
272  }
273  writer_head.fetch_and_store(NULL);
274  if (I != writer_tail.compare_and_swap(NULL, I)) { // an incoming writer is in the process of being added
275  spin_wait_while_eq(I->next, (scoped_lock *)NULL); // wait for new writer to be added
276  __TBB_ASSERT(I->next, "There should be a node following the last writer.");
277  set_next_writer(I->next);
278  }
279  }
280 }
const uintptr_t WFLAG1
void spin_wait_while_eq(const volatile T &location, U value)
Spin WHILE the value of the variable is equal to a given value.
Definition: tbb_machine.h:394
tbb_thread::id my_current_writer
Writer that owns the mutex; tbb_thread::id() otherwise.
atomic< scoped_lock * > writer_head
The list of pending writers.
void unblock_readers()
Unblocks pending readers.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
atomic< scoped_lock * > writer_tail
The last node in the list of pending writers.
void set_next_writer(scoped_lock *w)
Sets writer_head to w and attempts to unblock.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p sync_releasing
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
const uintptr_t WFLAG2
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:116
uintptr_t fetch_and_and(atomic< uintptr_t > &operand, uintptr_t value)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id id
const uintptr_t RFLAG
Here is the call graph for this function:
Here is the caller graph for this function:

◆ internal_construct()

void tbb::interface5::reader_writer_lock::internal_construct ( )
private

Definition at line 71 of file reader_writer_lock.cpp.

References _T, id, ITT_SYNC_CREATE, my_current_writer, rdr_count_and_flags, reader_head, writer_head, and writer_tail.

Referenced by reader_writer_lock().

71  {
72  reader_head = NULL;
73  writer_head = NULL;
74  writer_tail = NULL;
77 #if TBB_USE_THREADING_TOOLS
78  ITT_SYNC_CREATE(this, _T("tbb::reader_writer_lock"), _T(""));
79 #endif /* TBB_USE_THREADING_TOOLS */
80 }
atomic< scoped_lock_read * > reader_head
The list of pending readers.
#define ITT_SYNC_CREATE(obj, type, name)
Definition: itt_notify.h:119
#define _T(string_literal)
Standard Windows style macro to markup the string literals.
Definition: itt_notify.h:62
tbb_thread::id my_current_writer
Writer that owns the mutex; tbb_thread::id() otherwise.
atomic< scoped_lock * > writer_head
The list of pending writers.
atomic< scoped_lock * > writer_tail
The last node in the list of pending writers.
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id id
Here is the caller graph for this function:

◆ internal_destroy()

void tbb::interface5::reader_writer_lock::internal_destroy ( )
private

Definition at line 82 of file reader_writer_lock.cpp.

References __TBB_ASSERT, rdr_count_and_flags, reader_head, writer_head, and writer_tail.

Referenced by ~reader_writer_lock().

82  {
83  __TBB_ASSERT(rdr_count_and_flags==0, "reader_writer_lock destroyed with pending readers/writers.");
84  __TBB_ASSERT(reader_head==NULL, "reader_writer_lock destroyed with pending readers.");
85  __TBB_ASSERT(writer_tail==NULL, "reader_writer_lock destroyed with pending writers.");
86  __TBB_ASSERT(writer_head==NULL, "reader_writer_lock destroyed with pending/active writers.");
87 }
atomic< scoped_lock_read * > reader_head
The list of pending readers.
atomic< scoped_lock * > writer_head
The list of pending writers.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
atomic< scoped_lock * > writer_tail
The last node in the list of pending writers.
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
Here is the caller graph for this function:

◆ is_current_writer()

bool tbb::interface5::reader_writer_lock::is_current_writer ( )
inlineprivate

Checks if current thread holds write lock.

Definition at line 288 of file reader_writer_lock.cpp.

References tbb::this_tbb_thread::get_id(), and my_current_writer.

Referenced by lock(), lock_read(), try_lock(), try_lock_read(), and unlock().

288  {
290 }
tbb_thread::id my_current_writer
Writer that owns the mutex; tbb_thread::id() otherwise.
tbb_thread::id get_id()
Definition: tbb_thread.h:317
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lock()

void tbb::interface5::reader_writer_lock::lock ( )

Acquires the reader_writer_lock for write.

If the lock is currently held in write mode by another context, the writer will block by spinning on a local variable. Exceptions thrown: improper_lock The context tries to acquire a reader_writer_lock that it already has write ownership of.

Definition at line 93 of file reader_writer_lock.cpp.

References tbb::internal::eid_improper_lock, is_current_writer(), scoped_lock, start_write(), tbb::internal::throw_exception(), and void.

Referenced by tbb::interface5::reader_writer_lock::scoped_lock::internal_construct(), and tbb::interface5::reader_writer_lock::scoped_lock_read::internal_construct().

93  {
94  if (is_current_writer()) { // recursive lock attempt
95  // we don't support recursive writer locks; throw exception
97  }
98  else {
99  scoped_lock *a_writer_lock = new scoped_lock();
100  (void) start_write(a_writer_lock);
101  }
102 }
bool is_current_writer()
Checks if current thread holds write lock.
bool start_write(scoped_lock *)
Attempts to acquire write lock.
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lock_read()

void tbb::interface5::reader_writer_lock::lock_read ( )

Acquires the reader_writer_lock for read.

If the lock is currently held by a writer, this reader will block and wait until the writers are done. Exceptions thrown: improper_lock The context tries to acquire a reader_writer_lock that it already has write ownership of.

Definition at line 180 of file reader_writer_lock.cpp.

References tbb::internal::eid_improper_lock, is_current_writer(), start_read(), and tbb::internal::throw_exception().

180  {
181  if (is_current_writer()) { // recursive lock attempt
182  // we don't support writer->reader downgrade; throw exception
184  }
185  else {
186  scoped_lock_read a_reader_lock;
187  start_read(&a_reader_lock);
188  }
189 }
bool is_current_writer()
Checks if current thread holds write lock.
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
void start_read(scoped_lock_read *)
Attempts to acquire read lock.
Here is the call graph for this function:

◆ set_next_writer()

void tbb::interface5::reader_writer_lock::set_next_writer ( scoped_lock w)
private

Sets writer_head to w and attempts to unblock.

Definition at line 157 of file reader_writer_lock.cpp.

References __TBB_AtomicOR(), active, tbb::internal::atomic_impl< T >::compare_and_swap(), tbb::interface5::fetch_and_or(), rdr_count_and_flags, tbb::interface5::RFLAG, tbb::interface5::spin_wait_until_and(), tbb::interface5::spin_wait_while_geq(), tbb::interface5::reader_writer_lock::scoped_lock::status, waiting_nonblocking, and writer_head.

Referenced by end_write(), and start_write().

157  {
158  writer_head = W;
159  if (W->status == waiting_nonblocking) {
161  W->status = active;
162  }
163  }
164  else {
165  if (fetch_and_or(rdr_count_and_flags, WFLAG1) & RFLAG) { // reader present
166  spin_wait_until_and(rdr_count_and_flags, WFLAG2); // block until readers set WFLAG2
167  }
168  else { // no reader in timing window
170  }
171  spin_wait_while_geq(rdr_count_and_flags, RC_INCR); // block until readers finish
172  W->status = active;
173  }
174 }
const uintptr_t WFLAG1
atomic< scoped_lock * > writer_head
The list of pending writers.
void spin_wait_until_and(const volatile T &location, U value)
Spin UNTIL (location & value) is true.
const uintptr_t RC_INCR
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
const uintptr_t WFLAG2
value_type compare_and_swap(value_type value, value_type comparand)
Definition: atomic.h:285
void spin_wait_while_geq(const volatile T &location, U value)
Spin WHILE the value at the location is greater than or equal to a given value.
uintptr_t fetch_and_or(atomic< uintptr_t > &operand, uintptr_t value)
void __TBB_AtomicOR(volatile void *operand, uintptr_t addend)
Definition: tbb_machine.h:881
const uintptr_t RFLAG
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_read()

void tbb::interface5::reader_writer_lock::start_read ( scoped_lock_read I)
private

Attempts to acquire read lock.

If unavailable, spins in blocking case, returns false in non-blocking case.

Definition at line 209 of file reader_writer_lock.cpp.

References __TBB_ASSERT, active, tbb::interface5::fetch_and_or(), ITT_NOTIFY, tbb::interface5::reader_writer_lock::scoped_lock_read::next, tbb::interface5::RC_INCR, rdr_count_and_flags, reader_head, tbb::internal::spin_wait_while_eq(), tbb::interface5::reader_writer_lock::scoped_lock_read::status, unblock_readers(), and waiting.

Referenced by lock_read().

209  {
210  ITT_NOTIFY(sync_prepare, this);
211  I->next = reader_head.fetch_and_store(I);
212  if (!I->next) { // first arriving reader in my group; set RFLAG, test writer flags
213  // unblock and/or update statuses of non-blocking readers
214  if (!(fetch_and_or(rdr_count_and_flags, RFLAG) & (WFLAG1+WFLAG2))) { // no writers
215  unblock_readers();
216  }
217  }
218  __TBB_ASSERT(I->status == waiting || I->status == active, "Lock requests should be waiting or active before blocking.");
219  spin_wait_while_eq(I->status, waiting); // block
220  if (I->next) {
221  __TBB_ASSERT(I->next->status == waiting, NULL);
223  I->next->status = active; // wake successor
224  }
225  ITT_NOTIFY(sync_acquired, this);
226 }
atomic< scoped_lock_read * > reader_head
The list of pending readers.
const uintptr_t WFLAG1
void spin_wait_while_eq(const volatile T &location, U value)
Spin WHILE the value of the variable is equal to a given value.
Definition: tbb_machine.h:394
void unblock_readers()
Unblocks pending readers.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
const uintptr_t RC_INCR
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
const uintptr_t WFLAG2
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:116
uintptr_t fetch_and_or(atomic< uintptr_t > &operand, uintptr_t value)
const uintptr_t RFLAG
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_write()

bool tbb::interface5::reader_writer_lock::start_write ( scoped_lock I)
private

Attempts to acquire write lock.

If unavailable, spins in blocking case, returns false in non-blocking case.

Definition at line 118 of file reader_writer_lock.cpp.

References __TBB_ASSERT, tbb::this_tbb_thread::get_id(), id, ITT_NOTIFY, my_current_writer, tbb::interface5::reader_writer_lock::scoped_lock::next, set_next_writer(), tbb::internal::spin_wait_while_eq(), tbb::interface5::reader_writer_lock::scoped_lock::status, waiting, waiting_nonblocking, writer_head, and writer_tail.

Referenced by lock(), and try_lock().

118  {
120  scoped_lock *pred = NULL;
121  if (I->status == waiting_nonblocking) {
122  if ((pred = writer_tail.compare_and_swap(I, NULL)) != NULL) {
123  delete I;
124  return false;
125  }
126  }
127  else {
128  ITT_NOTIFY(sync_prepare, this);
129  pred = writer_tail.fetch_and_store(I);
130  }
131  if (pred)
132  pred->next = I;
133  else {
134  set_next_writer(I);
135  if (I->status == waiting_nonblocking) {
136  if (I->next) { // potentially more writers
137  set_next_writer(I->next);
138  }
139  else { // no more writers
140  writer_head.fetch_and_store(NULL);
141  if (I != writer_tail.compare_and_swap(NULL, I)) { // an incoming writer is in the process of being added
142  spin_wait_while_eq(I->next, (scoped_lock *)NULL); // wait for new writer to be added
143  __TBB_ASSERT(I->next, "There should be a node following the last writer.");
144  set_next_writer(I->next);
145  }
146  }
147  delete I;
148  return false;
149  }
150  }
151  spin_wait_while_eq(I->status, waiting);
152  ITT_NOTIFY(sync_acquired, this);
154  return true;
155 }
void spin_wait_while_eq(const volatile T &location, U value)
Spin WHILE the value of the variable is equal to a given value.
Definition: tbb_machine.h:394
tbb_thread::id my_current_writer
Writer that owns the mutex; tbb_thread::id() otherwise.
atomic< scoped_lock * > writer_head
The list of pending writers.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
atomic< scoped_lock * > writer_tail
The last node in the list of pending writers.
void set_next_writer(scoped_lock *w)
Sets writer_head to w and attempts to unblock.
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:116
tbb_thread::id get_id()
Definition: tbb_thread.h:317
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id id
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_lock()

bool tbb::interface5::reader_writer_lock::try_lock ( )

Tries to acquire the reader_writer_lock for write.

This function does not block. Return Value: True or false, depending on whether the lock is acquired or not. If the lock is already held by this acquiring context, try_lock() returns false.

Definition at line 107 of file reader_writer_lock.cpp.

References is_current_writer(), scoped_lock, start_write(), tbb::interface5::reader_writer_lock::scoped_lock::status, and waiting_nonblocking.

107  {
108  if (is_current_writer()) { // recursive lock attempt
109  return false;
110  }
111  else {
112  scoped_lock *a_writer_lock = new scoped_lock();
113  a_writer_lock->status = waiting_nonblocking;
114  return start_write(a_writer_lock);
115  }
116 }
bool is_current_writer()
Checks if current thread holds write lock.
bool start_write(scoped_lock *)
Attempts to acquire write lock.
Here is the call graph for this function:

◆ try_lock_read()

bool tbb::interface5::reader_writer_lock::try_lock_read ( )

Tries to acquire the reader_writer_lock for read.

This function does not block. Return Value: True or false, depending on whether the lock is acquired or not.

Definition at line 193 of file reader_writer_lock.cpp.

References is_current_writer(), ITT_NOTIFY, tbb::interface5::RC_INCR, rdr_count_and_flags, and tbb::interface5::WFLAG2.

193  {
194  if (is_current_writer()) { // recursive lock attempt
195  return false;
196  }
197  else {
198  if (rdr_count_and_flags.fetch_and_add(RC_INCR) & (WFLAG1+WFLAG2)) { // writers present
200  return false;
201  }
202  else { // no writers
203  ITT_NOTIFY(sync_acquired, this);
204  return true;
205  }
206  }
207 }
bool is_current_writer()
Checks if current thread holds write lock.
const uintptr_t WFLAG1
const uintptr_t RC_INCR
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
const uintptr_t WFLAG2
#define ITT_NOTIFY(name, obj)
Definition: itt_notify.h:116
Here is the call graph for this function:

◆ unblock_readers()

void tbb::interface5::reader_writer_lock::unblock_readers ( )
private

Unblocks pending readers.

Definition at line 228 of file reader_writer_lock.cpp.

References __TBB_ASSERT, __TBB_AtomicOR(), active, head, rdr_count_and_flags, reader_head, tbb::interface5::RFLAG, tbb::interface5::reader_writer_lock::scoped_lock_read::status, and waiting.

Referenced by end_write(), and start_read().

228  {
229  // clear rdr interest flag, increment rdr count
233  // indicate clear of window
236  }
237  // unblock waiting readers
238  scoped_lock_read *head = reader_head.fetch_and_store(NULL);
239  __TBB_ASSERT(head, NULL);
240  __TBB_ASSERT(head->status == waiting, NULL);
241  head->status = active;
242 }
atomic< scoped_lock_read * > reader_head
The list of pending readers.
const uintptr_t WFLAG1
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
const uintptr_t RC_INCR
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id head
atomic< uintptr_t > rdr_count_and_flags
Status of mutex.
const uintptr_t WFLAG2
void __TBB_AtomicOR(volatile void *operand, uintptr_t addend)
Definition: tbb_machine.h:881
const uintptr_t RFLAG
Here is the call graph for this function:
Here is the caller graph for this function:

◆ unlock()

void tbb::interface5::reader_writer_lock::unlock ( )

Releases the reader_writer_lock.

Definition at line 245 of file reader_writer_lock.cpp.

References __TBB_ASSERT, active, end_read(), end_write(), id, is_current_writer(), my_current_writer, and writer_head.

245  {
247  // A writer owns the lock
248  __TBB_ASSERT(is_current_writer(), "caller of reader_writer_lock::unlock() does not own the lock.");
249  __TBB_ASSERT(writer_head, NULL);
250  __TBB_ASSERT(writer_head->status==active, NULL);
251  scoped_lock *a_writer_lock = writer_head;
252  end_write(a_writer_lock);
253  __TBB_ASSERT(a_writer_lock != writer_head, "Internal error: About to turn writer_head into dangling reference.");
254  delete a_writer_lock;
255  } else {
256  end_read();
257  }
258 }
bool is_current_writer()
Checks if current thread holds write lock.
void end_read()
Relinquishes read lock by decrementing counter; last reader wakes pending writer. ...
tbb_thread::id my_current_writer
Writer that owns the mutex; tbb_thread::id() otherwise.
atomic< scoped_lock * > writer_head
The list of pending writers.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
void end_write(scoped_lock *)
Relinquishes write lock to next waiting writer or group of readers.
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id id
Here is the call graph for this function:

Friends And Related Function Documentation

◆ scoped_lock

friend class scoped_lock
friend

Definition at line 32 of file reader_writer_lock.h.

Referenced by lock(), and try_lock().

◆ scoped_lock_read

friend class scoped_lock_read
friend

Definition at line 33 of file reader_writer_lock.h.

Member Data Documentation

◆ my_current_writer

tbb_thread::id tbb::interface5::reader_writer_lock::my_current_writer
private

Writer that owns the mutex; tbb_thread::id() otherwise.

Definition at line 217 of file reader_writer_lock.h.

Referenced by end_write(), internal_construct(), is_current_writer(), start_write(), and unlock().

◆ rdr_count_and_flags

atomic<uintptr_t> tbb::interface5::reader_writer_lock::rdr_count_and_flags
private

◆ reader_head

atomic<scoped_lock_read*> tbb::interface5::reader_writer_lock::reader_head
private

The list of pending readers.

Definition at line 211 of file reader_writer_lock.h.

Referenced by internal_construct(), internal_destroy(), start_read(), and unblock_readers().

◆ writer_head

atomic<scoped_lock*> tbb::interface5::reader_writer_lock::writer_head
private

The list of pending writers.

Definition at line 213 of file reader_writer_lock.h.

Referenced by end_write(), internal_construct(), internal_destroy(), set_next_writer(), start_write(), and unlock().

◆ writer_tail

atomic<scoped_lock*> tbb::interface5::reader_writer_lock::writer_tail
private

The last node in the list of pending writers.

Definition at line 215 of file reader_writer_lock.h.

Referenced by end_write(), internal_construct(), internal_destroy(), and start_write().


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

Copyright © 2005-2019 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.