// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.concurrent;

import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.devtools.build.lib.concurrent.PriorityWorkerPool.TASKS_MAX_VALUE;

import com.google.common.annotations.VisibleForTesting;
import com.google.devtools.build.lib.unsafe.UnsafeProvider;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;
import sun.misc.Unsafe;

/**
 * A fixed-capacity concurrent FIFO for tasks used by {@link PriorityWorkerPool}.
 *
 * <p>This class is a higher performance, nearly garbage-free, but less flexible substitute for
 * {@link ConcurrentLinkedQueue},
 *
 * <ul>
 *   <li>The queue capacity is fixed.
 *   <li>The client must guarantee not to take more than it has added.
 *   <li>The client must have an fallback if {@link TaskFifo#tryAppend} fails.
 * </ul>
 *
 * <p>This class is inspired by Morrison, Adam, and Yehuda Afek. "Fast concurrent queues for x86
 * processors." Proceedings of the 18th ACM SIGPLAN symposium on Principles and practice of parallel
 * programming. 2013.
 */
final class TaskFifo {
  private static final Integer SKIP_SLOW_APPENDER = 1;

  /**
   * The power of 2 backing array capacity.
   *
   * <p>This is one more than the number of elements the queue can contain at one time. This helps
   * the efficiency of bits used to represent the number of elements enqueued. For example, the
   * number of bits needed to represent the element count for a queue of size 256 is 9, but only 8
   * bits are needed for a queue of size 255.
   */
  @VisibleForTesting static final int CAPACITY = TASKS_MAX_VALUE + 1;

  /** AND with this mask performs modulo {@link #CAPACITY}. */
  private static final int CAPACITY_MASK = CAPACITY - 1;

  /**
   * Circular buffer containing tasks and skip metadata.
   *
   * <p>The algorithm assigns to each caller of {@link #tryAppend} or {@link #take} a monotonically
   * increasing index (not including {@link #tryAppend} calls that would exceed capacity). {@link
   * #take} cannot be called more times than successful {@link tryAppend} calls by client
   * restriction. Thus each taker is assigned to a previous appender by matching index.
   *
   * <p>The naive algorithm based on the above would not be lock-free due to slow or descheduled
   * threads. For example, consider a taker assigned to an index where the corresponding appender's
   * thread has been descheduled before writing its task to the queue. When the taker observes its
   * assigned queue position, it does not see a value. The converse scenario is also possible. An
   * appender could see an occupied queue position while expecting {@code null} when a taker on the
   * same cyclic offset from a previous epoch is slow.
   *
   * <p>To resolve these situations, the threads that encounter them actively place a skip marker
   * into the queue that needs to be consumed by its counterpart. A taker that observes a null value
   * places a {@link Integer} {@code 1} to mark it, then skips to the next index. On seeing the
   * marker, the appender decrements it (with {@code 1} transitioning back to {@code null}). The
   * taker, when skipping to the next index, can expect to find a value there because an incomplete
   * append does not count as a successful one so there should be an extra complete append at a
   * subsequent index. Likewise, appenders that have looped all the way around to the same offset,
   * should expect to find an empty queue position due to capacity constraints.
   *
   * <p>Appenders that observe a value when expecting an empty position wrap the value with {@link
   * TaskWithSkippedAppends} then skip to the next available index. Slow takers decrement the counts
   * on the wrappers then skip to the next available index.
   *
   * <p>The skip marker has a count because the number of threads that could potentially be
   * descheduled at a particular index is only limited by the queue capacity, though more than one
   * should be extremely rare.
   *
   * <p>Each queue position contains one of the following.
   *
   * <ul>
   *   <li>{@code null} is an empty position.
   *   <li>{@link Runnable} is a position containing a task.
   *   <li>{@link Integer} is a count of takers that skipped the position because they observed a
   *       null value. The count corresponds to slow appenders at the position.
   *   <li>{@link TaskWithSkippedAppends} is a task with a count of appenders that skipped the
   *       position due to it being still occupied with a task. The count corresponds to slow takers
   *       assigned to the position.
   * </ul>
   *
   * <p>Correctness of the algorithm is straightforward. Anytime a taker skips a position, it adds a
   * count so that the same number of appenders skip that position and vice versa. Therefore the
   * number of takers and appenders skipping any given position stays balanced so the take and
   * append indices stay synchronized.
   */
  private final Object[] queue = new Object[CAPACITY];

  /**
   * Address of index for appending; incremented by appending.
   *
   * <p>The actual array offset is the value modulo {@link #CAPACITY}.
   */
  private final long appendIndexAddress;

  /**
   * Address of index for taking; incremented by taking.
   *
   * <p>The actual array offset is the value modulo {@link #CAPACITY}.
   */
  private final long takeIndexAddress;

  /**
   * The queue contains no more than this many tasks.
   *
   * <p>This is incremented before appending and decremented after taking.
   */
  private final long sizeAddress;

  /**
   * Constructor.
   *
   * <p>The caller owns the memory associated with the provided addresses.
   *
   * @param sizeAddress padded location of the {@code int} size of this queue.
   * @param takeIndexAddress padded location of the {@code int} take index.
   * @param appendIndexAddress padded location of the {@code int} append index.
   */
  TaskFifo(long sizeAddress, long appendIndexAddress, long takeIndexAddress) {
    this.sizeAddress = sizeAddress;
    this.appendIndexAddress = appendIndexAddress;
    this.takeIndexAddress = takeIndexAddress;

    // Explicitly initializes the provided addresses.
    UNSAFE.putInt(null, sizeAddress, 0);
    UNSAFE.putInt(null, appendIndexAddress, 0);
    UNSAFE.putInt(null, takeIndexAddress, 0);
  }

  /**
   * Tries to insert a task into the queue.
   *
   * @return true if successful, false if it would have exceeded the capacity.
   */
  boolean tryAppend(Runnable task) {
    // Optimistically increases size, and rolls back if it exceeds capacity.
    if (UNSAFE.getAndAddInt(null, sizeAddress, 1) >= TASKS_MAX_VALUE) {
      UNSAFE.getAndAddInt(null, sizeAddress, -1);
      return false;
    }

    do {
      int offset = getQueueOffset(UNSAFE.getAndAddInt(null, appendIndexAddress, 1));
      // In the common case, we can avoid an extra read.
      if (UNSAFE.compareAndSwapObject(queue, offset, null, task)) {
        return true;
      }
      do {
        // A plain read is sufficient here because this is always preceded by a failed CAS of the
        // same memory location.
        Object snapshot = UNSAFE.getObject(queue, offset);
        // It's possible that the taker outraced the snapshot above.
        if (snapshot == null) {
          if (UNSAFE.compareAndSwapObject(queue, offset, null, task)) {
            return true;
          }
          continue; // Refreshes the snapshot.
        }
        // There's some slowness that has to be resolved.
        Object target;
        if (snapshot instanceof Integer) {
          // There were previous takes without corresponding appends. Acknowledges a taker that
          // skipped this offset.
          int newCount = ((Integer) snapshot) - 1;
          target = newCount == 0 ? null : newCount;
        } else if (snapshot instanceof Runnable) {
          // A taker was slow.
          target = new TaskWithSkippedAppends((Runnable) snapshot, /* skippedAppendCount= */ 1);
        } else {
          // Multiple takers are slow. This should be very rare. Increments the skip count.
          target = ((TaskWithSkippedAppends) snapshot).incrementSkips();
        }
        if (UNSAFE.compareAndSwapObject(queue, offset, snapshot, target)) {
          break; // Success, skips to next.
        } // Otherwise refreshes the snapshot.
      } while (true);
    } while (true);
  }

  /**
   * Takes an available task.
   *
   * <p>This must not be called more times than {@link #tryAppend} has succeeded.
   */
  Runnable take() {
    do {
      int offset = getQueueOffset(UNSAFE.getAndAddInt(null, takeIndexAddress, 1));
      do {
        // A plain read is sufficient here.
        // 1. The initial read is supported by the client. In most cases, the client establishes the
        //    necessary happens-before relationship in honoring the constraint of no more takes than
        //    successful appends.
        // 2. On subsequent reads, this immediately follows a failed CAS of the same memory
        //    location, which refreshes the memory.
        Object snapshot = UNSAFE.getObject(queue, offset);
        if (snapshot instanceof Runnable) {
          // Attempts to take ownership of the task.
          if (UNSAFE.compareAndSwapObject(queue, offset, snapshot, null)) {
            UNSAFE.getAndAddInt(null, sizeAddress, -1);
            return (Runnable) snapshot;
          }
        } else {
          Object target;
          if (snapshot == null) {
            target = SKIP_SLOW_APPENDER;
          } else if (snapshot instanceof Integer) {
            // Increments the count due to multiple slow appenders, which should be very rare.
            target = ((Integer) snapshot).intValue() + 1;
          } else {
            // There have been appends without corresponding takes. Acknowledges one skip.
            target = ((TaskWithSkippedAppends) snapshot).decrementSkips();
          }
          if (UNSAFE.compareAndSwapObject(queue, offset, snapshot, target)) {
            break; // Success, skips to next.
          } // Otherwise refreshes the snapshot.
        }
      } while (true);
    } while (true);
  }

  int size() {
    return UNSAFE.getIntVolatile(null, sizeAddress);
  }

  void clear() {
    UNSAFE.putInt(null, sizeAddress, 0);
    UNSAFE.putInt(null, appendIndexAddress, 0);
    UNSAFE.putInt(null, takeIndexAddress, 0);
    Arrays.fill(queue, null);
  }

  @Override
  public String toString() {
    int appendIndex = UNSAFE.getIntVolatile(null, appendIndexAddress);
    int takeIndex = UNSAFE.getIntVolatile(null, takeIndexAddress);
    var helper =
        toStringHelper(this)
            .add("size", UNSAFE.getIntVolatile(null, sizeAddress))
            .add("appendIndex", String.format("%d (%d)", appendIndex, appendIndex & CAPACITY_MASK))
            .add("takeIndex", String.format("%d (%d)", takeIndex, takeIndex & CAPACITY_MASK));
    StringBuilder buf = new StringBuilder("[");
    for (int i = 0; i < CAPACITY; ++i) {
      if (i > 0) {
        buf.append(',');
      }
      if (i % 10 == 0) {
        buf.append(i).append(':');
      }
      var elt = queue[i];
      if (elt == null) {
        buf.append('0');
      } else if (elt instanceof Runnable) {
        buf.append('1');
      } else if (elt instanceof Integer) {
        buf.append('S').append(elt);
      } else {
        buf.append('T').append(((TaskWithSkippedAppends) elt).skippedAppendCount);
      }
    }
    helper.add("queue", buf.append(']').toString());
    return helper.toString();
  }

  @VisibleForTesting
  Object[] getQueueForTesting() {
    return queue;
  }

  private static int getQueueOffset(int index) {
    return TASKS_BASE + TASKS_SCALE * (index & CAPACITY_MASK);
  }

  @VisibleForTesting
  static class TaskWithSkippedAppends {
    private final Runnable task;
    private final int skippedAppendCount;

    private TaskWithSkippedAppends(Runnable task, int skippedAppendCount) {
      this.task = task;
      this.skippedAppendCount = skippedAppendCount;
    }

    private Object decrementSkips() {
      if (skippedAppendCount <= 1) {
        return task;
      }
      return new TaskWithSkippedAppends(task, skippedAppendCount - 1);
    }

    private TaskWithSkippedAppends incrementSkips() {
      return new TaskWithSkippedAppends(task, skippedAppendCount + 1);
    }

    @VisibleForTesting
    Runnable taskForTesting() {
      return task;
    }

    @VisibleForTesting
    int skippedAppendCountForTesting() {
      return skippedAppendCount;
    }
  }

  private static final Unsafe UNSAFE = UnsafeProvider.unsafe();

  private static final int TASKS_BASE = Unsafe.ARRAY_OBJECT_BASE_OFFSET;
  private static final int TASKS_SCALE = Unsafe.ARRAY_OBJECT_INDEX_SCALE;
}
