| 1900 | |
| 1901 | template<typename U> |
| 1902 | bool dequeue(U &element) { |
| 1903 | auto tail = this->tailIndex.load(std::memory_order_relaxed); |
| 1904 | auto overcommit = this->dequeueOvercommit.load(std::memory_order_relaxed); |
| 1905 | if (details::circular_less_than<index_t>( |
| 1906 | this->dequeueOptimisticCount.load(std::memory_order_relaxed) - overcommit, tail)) { |
| 1907 | // Might be something to dequeue, let's give it a try |
| 1908 | |
| 1909 | // Note that this if is purely for performance purposes in the common case when the queue is |
| 1910 | // empty and the values are eventually consistent -- we may enter here spuriously. |
| 1911 | |
| 1912 | // Note that whatever the values of overcommit and tail are, they are not going to change (unless we |
| 1913 | // change them) and must be the same value at this point (inside the if) as when the if condition was |
| 1914 | // evaluated. |
| 1915 | |
| 1916 | // We insert an acquire fence here to synchronize-with the release upon incrementing dequeueOvercommit below. |
| 1917 | // This ensures that whatever the value we got loaded into overcommit, the load of dequeueOptisticCount in |
| 1918 | // the fetch_add below will result in a value at least as recent as that (and therefore at least as large). |
| 1919 | // Note that I believe a compiler (signal) fence here would be sufficient due to the nature of fetch_add (all |
| 1920 | // read-modify-write operations are guaranteed to work on the latest value in the modification order), but |
| 1921 | // unfortunately that can't be shown to be correct using only the C++11 standard. |
| 1922 | // See http://stackoverflow.com/questions/18223161/what-are-the-c11-memory-ordering-guarantees-in-this-corner-case |
| 1923 | std::atomic_thread_fence(std::memory_order_acquire); |
| 1924 | |
| 1925 | // Increment optimistic counter, then check if it went over the boundary |
| 1926 | auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(1, std::memory_order_relaxed); |
| 1927 | |
| 1928 | // Note that since dequeueOvercommit must be <= dequeueOptimisticCount (because dequeueOvercommit is only ever |
| 1929 | // incremented after dequeueOptimisticCount -- this is enforced in the `else` block below), and since we now |
| 1930 | // have a version of dequeueOptimisticCount that is at least as recent as overcommit (due to the release upon |
| 1931 | // incrementing dequeueOvercommit and the acquire above that synchronizes with it), overcommit <= myDequeueCount. |
| 1932 | assert(overcommit <= myDequeueCount); |
| 1933 | |
| 1934 | // Note that we reload tail here in case it changed; it will be the same value as before or greater, since |
| 1935 | // this load is sequenced after (happens after) the earlier load above. This is supported by read-read |
| 1936 | // coherency (as defined in the standard), explained here: http://en.cppreference.com/w/cpp/atomic/memory_order |
| 1937 | tail = this->tailIndex.load(std::memory_order_acquire); |
| 1938 | if (details::likely( |
| 1939 | details::circular_less_than<index_t>(myDequeueCount - overcommit, tail))) { |
| 1940 | // Guaranteed to be at least one element to dequeue! |
| 1941 | |
| 1942 | // Get the index. Note that since there's guaranteed to be at least one element, this |
| 1943 | // will never exceed tail. We need to do an acquire-release fence here since it's possible |
| 1944 | // that whatever condition got us to this point was for an earlier enqueued element (that |
| 1945 | // we already see the memory effects for), but that by the time we increment somebody else |
| 1946 | // has incremented it, and we need to see the memory effects for *that* element, which is |
| 1947 | // in such a case is necessarily visible on the thread that incremented it in the first |
| 1948 | // place with the more current condition (they must have acquired a tail that is at least |
| 1949 | // as recent). |
| 1950 | auto index = this->headIndex.fetch_add(1, std::memory_order_acq_rel); |
| 1951 | |
| 1952 | |
| 1953 | // Determine which block the element is in |
| 1954 | |
| 1955 | auto localBlockIndex = blockIndex.load(std::memory_order_acquire); |
| 1956 | auto localBlockIndexHead = localBlockIndex->front.load(std::memory_order_acquire); |
| 1957 | |
| 1958 | // We need to be careful here about subtracting and dividing because of index wrap-around. |
| 1959 | // When an index wraps, we need to preserve the sign of the offset when dividing it by the |
no test coverage detected