Multi producer safe.
| 66 | |
| 67 | // Multi producer safe. |
| 68 | void enqueue(T* element) |
| 69 | { |
| 70 | // A `nullptr` is used to denote an empty queue when doing a |
| 71 | // `dequeue()` so producers can't use it as an element. |
| 72 | CHECK_NOTNULL(element); |
| 73 | |
| 74 | auto newNode = new Node<T>(element); |
| 75 | |
| 76 | // Exchange is guaranteed to only give the old value to one |
| 77 | // producer, so this is safe and wait-free. |
| 78 | auto oldhead = head.exchange(newNode, std::memory_order_acq_rel); |
| 79 | |
| 80 | // At this point if this thread context switches out we may block |
| 81 | // the consumer from doing a dequeue (see below). Eventually we'll |
| 82 | // unblock the consumer once we run again and execute the next |
| 83 | // line of code. |
| 84 | oldhead->next.store(newNode, std::memory_order_release); |
| 85 | } |
| 86 | |
| 87 | // Single consumer only. |
| 88 | T* dequeue() |