| 124 | } |
| 125 | |
| 126 | void read_unlock() |
| 127 | { |
| 128 | // NOTE: We need to satisfy the waiter future outside the |
| 129 | // critical section because it might trigger callbacks which |
| 130 | // try to reacquire a read or write lock. |
| 131 | Option<Waiter> waiter; |
| 132 | |
| 133 | synchronized (data->lock) { |
| 134 | CHECK(!data->write_locked); |
| 135 | CHECK_GT(data->read_locked, 0u); |
| 136 | |
| 137 | data->read_locked--; |
| 138 | |
| 139 | if (data->read_locked == 0u && !data->waiters.empty()) { |
| 140 | CHECK_EQ(data->waiters.front().type, Waiter::WRITE); |
| 141 | |
| 142 | waiter = std::move(data->waiters.front()); |
| 143 | data->waiters.pop(); |
| 144 | data->write_locked = true; |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | if (waiter.isSome()) { |
| 149 | waiter->promise.set(Nothing()); |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | private: |
| 154 | struct Waiter |