/*
 * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_UTILITIES_NONBLOCKINGQUEUE_INLINE_HPP
#define SHARE_UTILITIES_NONBLOCKINGQUEUE_INLINE_HPP

#include "utilities/nonblockingQueue.hpp"

#include "runtime/atomic.hpp"

template<typename T, T* volatile* (*next_ptr)(T&)>
T* NonblockingQueue<T, next_ptr>::next(const T& node) {
  return Atomic::load(next_ptr(const_cast<T&>(node)));
}

template<typename T, T* volatile* (*next_ptr)(T&)>
void NonblockingQueue<T, next_ptr>::set_next(T& node, T* new_next) {
  Atomic::store(next_ptr(node), new_next);
}

template<typename T, T* volatile* (*next_ptr)(T&)>
NonblockingQueue<T, next_ptr>::NonblockingQueue() : _head(nullptr), _tail(nullptr) {}

#ifdef ASSERT
template<typename T, T* volatile* (*next_ptr)(T&)>
NonblockingQueue<T, next_ptr>::~NonblockingQueue() {
  assert(_head == nullptr, "precondition");
  assert(_tail == nullptr, "precondition");
}
#endif

// The end_marker must be uniquely associated with the specific queue, in
// case queue elements can make their way through multiple queues.  A
// pointer to the queue itself (after casting) satisfies that requirement.
template<typename T, T* volatile* (*next_ptr)(T&)>
T* NonblockingQueue<T, next_ptr>::end_marker() const {
  return const_cast<T*>(reinterpret_cast<const T*>(this));
}

template<typename T, T* volatile* (*next_ptr)(T&)>
T* NonblockingQueue<T, next_ptr>::first() const {
  T* head = Atomic::load(&_head);
  return head == nullptr ? end_marker() : head;
}

template<typename T, T* volatile* (*next_ptr)(T&)>
bool NonblockingQueue<T, next_ptr>::is_end(const T* entry) const {
  return entry == end_marker();
}

template<typename T, T* volatile* (*next_ptr)(T&)>
bool NonblockingQueue<T, next_ptr>::empty() const {
  return Atomic::load(&_head) == nullptr;
}

template<typename T, T* volatile* (*next_ptr)(T&)>
size_t NonblockingQueue<T, next_ptr>::length() const {
  size_t result = 0;
  for (T* cur = first(); !is_end(cur); cur = next(*cur)) {
    ++result;
  }
  return result;
}

// An append operation atomically exchanges the new tail with the queue tail.
// It then sets the "next" value of the old tail to the head of the list being
// appended. If the old tail is null then the queue was empty, then the
// head of the list being appended is instead stored in the queue head.
//
// This means there is a period between the exchange and the old tail update
// where the queue sequence is split into two parts, the list from the queue
// head to the old tail, and the list being appended.  If there are concurrent
// push/append operations, each may introduce another such segment.  But they
// all eventually get resolved by their respective updates of their old tail's
// "next" value.  This also means that try_pop operation must handle an object
// differently depending on its "next" value.
//
// A push operation is just a degenerate append, where the object being pushed
// is both the head and the tail of the list being appended.
template<typename T, T* volatile* (*next_ptr)(T&)>
void NonblockingQueue<T, next_ptr>::append(T& first, T& last) {
  assert(next(last) == nullptr, "precondition");
  // Make last the new end of the queue.  Any further push/appends will
  // extend after last.  We will try to extend from the previous end of
  // queue.
  set_next(last, end_marker());
  T* old_tail = Atomic::xchg(&_tail, &last);
  if (old_tail == nullptr) {
    // If old_tail is null then the queue was empty, and _head must also be
    // null. The correctness of this assertion depends on try_pop clearing
    // first _head then _tail when taking the last entry.
    assert(Atomic::load(&_head) == nullptr, "invariant");
    // Fall through to common update of _head.
  } else if (is_end(Atomic::cmpxchg(next_ptr(*old_tail), end_marker(), &first))) {
    // Successfully extended the queue list from old_tail to first.  No
    // other push/append could have competed with us, because we claimed
    // old_tail for extension.  We won any races with try_pop by changing
    // away from end-marker.  So we're done.
    //
    // Note that ABA is possible here.  A concurrent try_pop could take
    // old_tail before our update of old_tail's next_ptr, old_tail gets
    // recycled and re-added to the end of this queue, and then we
    // successfully cmpxchg, making the list in _tail circular.  Callers
    // must ensure this can't happen.
    return;
  } else {
    // A concurrent try_pop has claimed old_tail, so it is no longer in the
    // list. The queue was logically empty.  _head is either null or
    // old_tail, depending on how far try_pop operations have progressed.
    DEBUG_ONLY(T* old_head = Atomic::load(&_head);)
    assert((old_head == nullptr) || (old_head == old_tail), "invariant");
    // Fall through to common update of _head.
  }
  // The queue was empty, and first should become the new _head.  The queue
  // will appear to be empty to any further try_pops until done.
  Atomic::store(&_head, &first);
}

template<typename T, T* volatile* (*next_ptr)(T&)>
bool NonblockingQueue<T, next_ptr>::try_pop(T** node_ptr) {
  // We only need memory_order_consume. Upgrade it to "load_acquire"
  // as the memory_order_consume API is not ready for use yet.
  T* old_head = Atomic::load_acquire(&_head);
  if (old_head == nullptr) {
    *node_ptr = nullptr;
    return true;                // Queue is empty.
  }

  T* next_node = Atomic::load_acquire(next_ptr(*old_head));
  if (!is_end(next_node)) {
    // [Clause 1]
    // There are several cases for next_node.
    // (1) next_node is the extension of the queue's list.
    // (2) next_node is null, because a competing try_pop took old_head.
    // (3) next_node is the extension of some unrelated list, because a
    // competing try_pop took old_head and put it in some other list.
    //
    // Attempt to advance the list, replacing old_head with next_node in
    // _head.  The success or failure of that attempt, along with the value
    // of next_node, are used to partially determine which case we're in and
    // how to proceed.  In particular, advancement will fail for case (3).
    if (old_head != Atomic::cmpxchg(&_head, old_head, next_node)) {
      // [Clause 1a]
      // The cmpxchg to advance the list failed; a concurrent try_pop won
      // the race and claimed old_head.  This can happen for any of the
      // next_node cases.
      return false;
    } else if (next_node == nullptr) {
      // [Clause 1b]
      // The cmpxchg to advance the list succeeded, but a concurrent try_pop
      // has already claimed old_head (see [Clause 2] - old_head was the last
      // entry in the list) by nulling old_head's next field.  The advance set
      // _head to null, "helping" the competing try_pop.  _head will remain
      // nullptr until a subsequent push/append.  This is a lost race, and we
      // report it as such for consistency, though we could report the queue
      // was empty.  We don't attempt to further help [Clause 2] by also
      // trying to set _tail to nullptr, as that would just ensure that one or
      // the other cmpxchg is a wasted failure.
      return false;
    } else {
      // [Clause 1c]
      // Successfully advanced the list and claimed old_head.  next_node was
      // in the extension of the queue's list.  Return old_head after
      // unlinking it from next_node.
      set_next(*old_head, nullptr);
      *node_ptr = old_head;
      return true;
    }

  } else if (is_end(Atomic::cmpxchg(next_ptr(*old_head), next_node, (T*)nullptr))) {
    // [Clause 2]
    // Old_head was the last entry and we've claimed it by setting its next
    // value to null.  However, this leaves the queue in disarray.  Fix up
    // the queue, possibly in conjunction with other concurrent operations.
    // Any further try_pops will consider the queue empty until a
    // push/append completes by installing a new head.

    // The order of the two cmpxchgs doesn't matter algorithmically, but
    // dealing with _head first gives a stronger invariant in append, and is
    // also consistent with [Clause 1b].

    // Attempt to change the queue head from old_head to null.  Failure of
    // the cmpxchg indicates a concurrent operation updated _head first.  That
    // could be either a push/append or a try_pop in [Clause 1b].
    Atomic::cmpxchg(&_head, old_head, (T*)nullptr);

    // Attempt to change the queue tail from old_head to null.  Failure of
    // the cmpxchg indicates that a concurrent push/append updated _tail first.
    // That operation will eventually recognize the old tail (our old_head) is
    // no longer in the list and update _head from the list being appended.
    Atomic::cmpxchg(&_tail, old_head, (T*)nullptr);

    // The queue has been restored to order, and we can return old_head.
    *node_ptr = old_head;
    return true;

  } else {
    // [Clause 3]
    // Old_head was the last entry in the list, but either a concurrent
    // try_pop claimed it first or a concurrent push/append extended the
    // list from it.  Either way, we lost the race to claim it.
    return false;
  }
}

template<typename T, T* volatile* (*next_ptr)(T&)>
T* NonblockingQueue<T, next_ptr>::pop() {
  T* result = nullptr;
  // Typically try_pop() will succeed without retrying many times, thus we
  // omit SpinPause in the loop body.  SpinPause or yield may be worthwhile
  // in rare, highly contended cases, and client code could implement such
  // with try_pop().
  while (!try_pop(&result)) {}
  return result;
}

template<typename T, T* volatile* (*next_ptr)(T&)>
Pair<T*, T*> NonblockingQueue<T, next_ptr>::take_all() {
  T* tail = Atomic::load(&_tail);
  if (tail != nullptr) set_next(*tail, nullptr); // Clear end marker.
  Pair<T*, T*> result(Atomic::load(&_head), tail);
  Atomic::store(&_head, (T*)nullptr);
  Atomic::store(&_tail, (T*)nullptr);
  return result;
}

#endif // SHARE_UTILITIES_NONBLOCKINGQUEUE_INLINE_HPP
