//===- subzero/src/IceThreading.h - Threading functions ---------*- C++ -*-===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares threading-related functions.
///
//===----------------------------------------------------------------------===//

#ifndef SUBZERO_SRC_ICETHREADING_H
#define SUBZERO_SRC_ICETHREADING_H

#include "IceDefs.h"

#include <condition_variable>
#include <mutex>

namespace Ice {

/// BoundedProducerConsumerQueue is a work queue that allows multiple producers
/// and multiple consumers. A producer adds entries using blockingPush(), and
/// may block if the queue is "full". A producer uses notifyEnd() to indicate
/// that no more entries will be added. A consumer removes an item using
/// blockingPop(), which will return nullptr if notifyEnd() has been called and
/// the queue is empty (it never returns nullptr if the queue contained any
/// items).
///
/// The MaxSize ctor arg controls the maximum size the queue can grow to
/// (subject to a hard limit of MaxStaticSize-1). The Sequential arg indicates
/// purely sequential execution in which the single thread should never wait().
///
/// Two condition variables are used in the implementation. GrewOrEnded signals
/// a waiting worker that a producer has changed the state of the queue. Shrunk
/// signals a blocked producer that a consumer has changed the state of the
/// queue.
///
/// The methods begin with Sequential-specific code to be most clear. The lock
/// and condition variables are not used in the Sequential case.
///
/// Internally, the queue is implemented as a circular array of size
/// MaxStaticSize, where the queue boundaries are denoted by the Front and Back
/// fields. Front==Back indicates an empty queue.
template <typename T, size_t MaxStaticSize = 128>
class BoundedProducerConsumerQueue {
  BoundedProducerConsumerQueue() = delete;
  BoundedProducerConsumerQueue(const BoundedProducerConsumerQueue &) = delete;
  BoundedProducerConsumerQueue &
  operator=(const BoundedProducerConsumerQueue &) = delete;

public:
  BoundedProducerConsumerQueue(bool Sequential, size_t MaxSize = MaxStaticSize)
      : MaxSize(std::min(MaxSize, MaxStaticSize)), Sequential(Sequential) {}
  void blockingPush(T *Item) {
    {
      std::unique_lock<GlobalLockType> L(Lock);
      // If the work queue is already "full", wait for a consumer to grab an
      // element and shrink the queue.
      Shrunk.wait(L, [this] { return size() < MaxSize || Sequential; });
      push(Item);
    }
    GrewOrEnded.notify_one();
  }
  T *blockingPop() {
    T *Item = nullptr;
    bool ShouldNotifyProducer = false;
    {
      std::unique_lock<GlobalLockType> L(Lock);
      GrewOrEnded.wait(L, [this] { return IsEnded || !empty() || Sequential; });
      if (!empty()) {
        Item = pop();
        ShouldNotifyProducer = !IsEnded;
      }
    }
    if (ShouldNotifyProducer)
      Shrunk.notify_one();
    return Item;
  }
  void notifyEnd() {
    {
      std::lock_guard<GlobalLockType> L(Lock);
      IsEnded = true;
    }
    GrewOrEnded.notify_all();
  }

private:
  const static size_t MaxStaticSizeMask = MaxStaticSize - 1;
  static_assert(!(MaxStaticSize & (MaxStaticSize - 1)),
                "MaxStaticSize must be a power of 2");

  ICE_CACHELINE_BOUNDARY;
  /// WorkItems and Lock are read/written by all.
  T *WorkItems[MaxStaticSize];
  ICE_CACHELINE_BOUNDARY;
  /// Lock guards access to WorkItems, Front, Back, and IsEnded.
  GlobalLockType Lock;

  ICE_CACHELINE_BOUNDARY;
  /// GrewOrEnded is written by the producers and read by the consumers. It is
  /// notified (by the producer) when something is added to the queue, in case
  /// consumers are waiting for a non-empty queue.
  std::condition_variable GrewOrEnded;
  /// Back is the index into WorkItems[] of where the next element will be
  /// pushed. (More precisely, Back&MaxStaticSize is the index.) It is written
  /// by the producers, and read by all via size() and empty().
  size_t Back = 0;

  ICE_CACHELINE_BOUNDARY;
  /// Shrunk is notified (by the consumer) when something is removed from the
  /// queue, in case a producer is waiting for the queue to drop below maximum
  /// capacity. It is written by the consumers and read by the producers.
  std::condition_variable Shrunk;
  /// Front is the index into WorkItems[] of the oldest element, i.e. the next
  /// to be popped. (More precisely Front&MaxStaticSize is the index.) It is
  /// written by the consumers, and read by all via size() and empty().
  size_t Front = 0;

  ICE_CACHELINE_BOUNDARY;

  /// MaxSize and Sequential are read by all and written by none.
  const size_t MaxSize;
  const bool Sequential;
  /// IsEnded is read by the consumers, and only written once by the producer.
  bool IsEnded = false;

  /// The lock must be held when the following methods are called.
  bool empty() const { return Front == Back; }
  size_t size() const { return Back - Front; }
  void push(T *Item) {
    WorkItems[Back++ & MaxStaticSizeMask] = Item;
    assert(size() <= MaxStaticSize);
  }
  T *pop() {
    assert(!empty());
    return WorkItems[Front++ & MaxStaticSizeMask];
  }
};

/// EmitterWorkItem is a simple wrapper around a pointer that represents a work
/// item to be emitted, i.e. a function or a set of global declarations and
/// initializers, and it includes a sequence number so that work items can be
/// emitted in a particular order for deterministic output. It acts like an
/// interface class, but instead of making the classes of interest inherit from
/// EmitterWorkItem, it wraps pointers to these classes. Some space is wasted
/// compared to storing the pointers in a union, but not too much due to the
/// work granularity.
class EmitterWorkItem {
  EmitterWorkItem() = delete;
  EmitterWorkItem(const EmitterWorkItem &) = delete;
  EmitterWorkItem &operator=(const EmitterWorkItem &) = delete;

public:
  /// ItemKind can be one of the following:
  ///
  /// WI_Nop: No actual work. This is a placeholder to maintain sequence numbers
  /// in case there is a translation error.
  ///
  /// WI_GlobalInits: A list of global declarations and initializers.
  ///
  /// WI_Asm: A function that has already had emitIAS() called on it. The work
  /// is transferred via the Assembler buffer, and the originating Cfg has been
  /// deleted (to recover lots of memory).
  ///
  /// WI_Cfg: A Cfg that has not yet had emit() or emitIAS() called on it. This
  /// is only used as a debugging configuration when we want to emit "readable"
  /// assembly code, possibly annotated with liveness and other information only
  /// available in the Cfg and not in the Assembler buffer.
  enum ItemKind { WI_Nop, WI_GlobalInits, WI_Asm, WI_Cfg };
  /// Constructor for a WI_Nop work item.
  explicit EmitterWorkItem(uint32_t Seq);
  /// Constructor for a WI_GlobalInits work item.
  EmitterWorkItem(uint32_t Seq, VariableDeclarationList *D);
  /// Constructor for a WI_Asm work item.
  EmitterWorkItem(uint32_t Seq, Assembler *A);
  /// Constructor for a WI_Cfg work item.
  EmitterWorkItem(uint32_t Seq, Cfg *F);
  uint32_t getSequenceNumber() const { return Sequence; }
  ItemKind getKind() const { return Kind; }
  void setGlobalInits(std::unique_ptr<VariableDeclarationList> GloblInits);
  std::unique_ptr<VariableDeclarationList> getGlobalInits();
  std::unique_ptr<Assembler> getAsm();
  std::unique_ptr<Cfg> getCfg();

private:
  const uint32_t Sequence;
  const ItemKind Kind;
  std::unique_ptr<VariableDeclarationList> GlobalInits;
  std::unique_ptr<Assembler> Function;
  std::unique_ptr<Cfg> RawFunc;
};

} // end of namespace Ice

#endif // SUBZERO_SRC_ICETHREADING_H
