| 200 | } |
| 201 | |
| 202 | void thread(unsigned int tid) |
| 203 | { |
| 204 | if (tid == 0) { |
| 205 | // Producer |
| 206 | for (int i = 0; i != NUM_VALUES; ++i) { |
| 207 | hash->insert(i, &values[i]); |
| 208 | useCounts[i].store(ThreadCount / 2, std::memory_order_release); |
| 209 | } |
| 210 | } |
| 211 | else { |
| 212 | // Consumer |
| 213 | for (int i = 0; i != NUM_VALUES; ++i) { |
| 214 | auto useCount = useCounts[i].fetch_add(-1, std::memory_order_acquire); |
| 215 | auto val = hash->find(i); |
| 216 | bool isRemoved = removed[i].load(std::memory_order_relaxed); |
| 217 | auto current = useCounts[i].fetch_add(0, std::memory_order_release); |
| 218 | if (useCount > 0 && (current > 0 || current == 0 && useCount == 1)) { |
| 219 | RL_ASSERT(val != nullptr && *val == i && !isRemoved); |
| 220 | } |
| 221 | if (useCount == 1) { |
| 222 | val = hash->remove(i); |
| 223 | RL_ASSERT(val != nullptr && *val == i && !removed[i].load(std::memory_order_relaxed)); |
| 224 | removed[i].store(true, std::memory_order_release); |
| 225 | } |
| 226 | } |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | void after() |
| 231 | { |