| 120 | } |
| 121 | |
| 122 | bool reader_writer_lock::start_write(scoped_lock *I) { |
| 123 | tbb_thread::id id = this_tbb_thread::get_id(); |
| 124 | scoped_lock *pred = NULL; |
| 125 | if (I->status == waiting_nonblocking) { |
| 126 | if ((pred = writer_tail.compare_and_swap(I, NULL)) != NULL) { |
| 127 | delete I; |
| 128 | return false; |
| 129 | } |
| 130 | } |
| 131 | else { |
| 132 | ITT_NOTIFY(sync_prepare, this); |
| 133 | pred = writer_tail.fetch_and_store(I); |
| 134 | } |
| 135 | if (pred) |
| 136 | pred->next = I; |
| 137 | else { |
| 138 | set_next_writer(I); |
| 139 | if (I->status == waiting_nonblocking) { |
| 140 | if (I->next) { // potentially more writers |
| 141 | set_next_writer(I->next); |
| 142 | } |
| 143 | else { // no more writers |
| 144 | writer_head.fetch_and_store(NULL); |
| 145 | if (I != writer_tail.compare_and_swap(NULL, I)) { // an incoming writer is in the process of being added |
| 146 | spin_wait_while_eq(I->next, (scoped_lock *)NULL); // wait for new writer to be added |
| 147 | __TBB_ASSERT(I->next, "There should be a node following the last writer."); |
| 148 | set_next_writer(I->next); |
| 149 | } |
| 150 | } |
| 151 | delete I; |
| 152 | return false; |
| 153 | } |
| 154 | } |
| 155 | spin_wait_while_eq(I->status, waiting); |
| 156 | ITT_NOTIFY(sync_acquired, this); |
| 157 | my_current_writer = id; |
| 158 | return true; |
| 159 | } |
| 160 | |
| 161 | void reader_writer_lock::set_next_writer(scoped_lock *W) { |
| 162 | writer_head = W; |
no test coverage detected