// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Ported by the Dart team to Dart.

// This is a Dart implementation of the Richards benchmark from:
//
//    http://www.cl.cam.ac.uk/~mr10/Bench.html
//
// The benchmark was originally implemented in BCPL by
// Martin Richards.

import 'package:benchmark_harness/benchmark_harness.dart';

void main() {
  const Richards().report();
}

/// Richards imulates the task dispatcher of an operating system.
class Richards extends BenchmarkBase {
  const Richards() : super('Richards');

  @override
  void run() {
    final Scheduler scheduler = Scheduler();
    scheduler.addIdleTask(ID_IDLE, 0, null, COUNT);

    Packet queue = Packet(null, ID_WORKER, KIND_WORK);
    queue = Packet(queue, ID_WORKER, KIND_WORK);
    scheduler.addWorkerTask(ID_WORKER, 1000, queue);

    queue = Packet(null, ID_DEVICE_A, KIND_DEVICE);
    queue = Packet(queue, ID_DEVICE_A, KIND_DEVICE);
    queue = Packet(queue, ID_DEVICE_A, KIND_DEVICE);
    scheduler.addHandlerTask(ID_HANDLER_A, 2000, queue);

    queue = Packet(null, ID_DEVICE_B, KIND_DEVICE);
    queue = Packet(queue, ID_DEVICE_B, KIND_DEVICE);
    queue = Packet(queue, ID_DEVICE_B, KIND_DEVICE);
    scheduler.addHandlerTask(ID_HANDLER_B, 3000, queue);

    scheduler.addDeviceTask(ID_DEVICE_A, 4000, null);

    scheduler.addDeviceTask(ID_DEVICE_B, 5000, null);

    scheduler.schedule();

    if (scheduler.queueCount != EXPECTED_QUEUE_COUNT ||
        scheduler.holdCount != EXPECTED_HOLD_COUNT) {
      print('Error during execution: queueCount = ${scheduler.queueCount}'
          ', holdCount = ${scheduler.holdCount}.');
    }
    if (EXPECTED_QUEUE_COUNT != scheduler.queueCount) {
      throw 'bad scheduler queue-count';
    }
    if (EXPECTED_HOLD_COUNT != scheduler.holdCount) {
      throw 'bad scheduler hold-count';
    }
  }

  static const int DATA_SIZE = 4;
  static const int COUNT = 1000;

  /// These two constants specify how many times a packet is queued and
  /// how many times a task is put on hold in a correct run of richards.
  /// They don't have any meaning a such but are characteristic of a
  /// correct run so if the actual queue or hold count is different from
  /// the expected there must be a bug in the implementation.
  static const int EXPECTED_QUEUE_COUNT = 2322;
  static const int EXPECTED_HOLD_COUNT = 928;

  static const int ID_IDLE = 0;
  static const int ID_WORKER = 1;
  static const int ID_HANDLER_A = 2;
  static const int ID_HANDLER_B = 3;
  static const int ID_DEVICE_A = 4;
  static const int ID_DEVICE_B = 5;
  static const int NUMBER_OF_IDS = 6;

  static const int KIND_DEVICE = 0;
  static const int KIND_WORK = 1;
}

/// A scheduler can be used to schedule a set of tasks based on their relative
/// priorities.  Scheduling is done by maintaining a list of task control blocks
/// which holds tasks and the data queue they are processing.
class Scheduler {
  int queueCount = 0;
  int holdCount = 0;
  TaskControlBlock? currentTcb;
  int currentId = Richards.ID_IDLE;
  TaskControlBlock? list;
  final List<TaskControlBlock?> blocks =
      List<TaskControlBlock?>.filled(Richards.NUMBER_OF_IDS, null);

  /// Add an idle task to this scheduler.
  void addIdleTask(int id, int priority, Packet? queue, int count) {
    addRunningTask(id, priority, queue, IdleTask(this, 1, count));
  }

  /// Add a work task to this scheduler.
  void addWorkerTask(int id, int priority, Packet? queue) {
    addTask(id, priority, queue, WorkerTask(this, Richards.ID_HANDLER_A, 0));
  }

  /// Add a handler task to this scheduler.
  void addHandlerTask(int id, int priority, Packet? queue) {
    addTask(id, priority, queue, HandlerTask(this));
  }

  /// Add a handler task to this scheduler.
  void addDeviceTask(int id, int priority, Packet? queue) {
    addTask(id, priority, queue, DeviceTask(this));
  }

  /// Add the specified task and mark it as running.
  void addRunningTask(int id, int priority, Packet? queue, Task task) {
    addTask(id, priority, queue, task);
    currentTcb!.setRunning();
  }

  /// Add the specified task to this scheduler.
  void addTask(int id, int priority, Packet? queue, Task task) {
    currentTcb = TaskControlBlock(list, id, priority, queue, task);
    list = currentTcb;
    blocks[id] = currentTcb;
  }

  /// Execute the tasks managed by this scheduler.
  void schedule() {
    currentTcb = list;
    while (currentTcb != null) {
      if (currentTcb!.isHeldOrSuspended()) {
        currentTcb = currentTcb!.link;
      } else {
        currentId = currentTcb!.id;
        currentTcb = currentTcb!.run();
      }
    }
  }

  /// Release a task that is currently blocked and return the next block to run.
  TaskControlBlock? release(int id) {
    final TaskControlBlock? tcb = blocks[id];
    if (tcb == null) return tcb;
    tcb.markAsNotHeld();
    if (tcb.priority > currentTcb!.priority) return tcb;
    return currentTcb;
  }

  /// Block the currently executing task and return the next task control block
  /// to run.  The blocked task will not be made runnable until it is explicitly
  /// released, even if new work is added to it.
  TaskControlBlock? holdCurrent() {
    holdCount++;
    currentTcb!.markAsHeld();
    return currentTcb!.link;
  }

  /// Suspend the currently executing task and return the next task
  /// control block to run.
  /// If new work is added to the suspended task it will be made runnable.
  TaskControlBlock suspendCurrent() {
    currentTcb!.markAsSuspended();
    return currentTcb!;
  }

  /// Add the specified packet to the end of the worklist used by the task
  /// associated with the packet and make the task runnable if it is currently
  /// suspended.
  TaskControlBlock? queue(Packet packet) {
    final TaskControlBlock? t = blocks[packet.id];
    if (t == null) return t;
    queueCount++;
    packet.link = null;
    packet.id = currentId;
    return t.checkPriorityAdd(currentTcb!, packet);
  }
}

/// A task control block manages a task and the queue of work packages
/// associated with it.
class TaskControlBlock {
  TaskControlBlock? link;
  int id; // The id of this block.
  int priority; // The priority of this block.
  Packet? queue; // The queue of packages to be processed by the task.
  Task task;
  int state;

  TaskControlBlock(this.link, this.id, this.priority, this.queue, this.task)
      : state = queue == null ? STATE_SUSPENDED : STATE_SUSPENDED_RUNNABLE;

  /// The task is running and is currently scheduled.
  static const int STATE_RUNNING = 0;

  /// The task has packets left to process.
  static const int STATE_RUNNABLE = 1;

  /// The task is not currently running. The task is not blocked as such and may
  /// be started by the scheduler.
  static const int STATE_SUSPENDED = 2;

  /// The task is blocked and cannot be run until it is explicitly released.
  static const int STATE_HELD = 4;

  static const int STATE_SUSPENDED_RUNNABLE = STATE_SUSPENDED | STATE_RUNNABLE;
  static const int STATE_NOT_HELD = ~STATE_HELD;

  void setRunning() {
    state = STATE_RUNNING;
  }

  void markAsNotHeld() {
    state = state & STATE_NOT_HELD;
  }

  void markAsHeld() {
    state = state | STATE_HELD;
  }

  bool isHeldOrSuspended() {
    return (state & STATE_HELD) != 0 || (state == STATE_SUSPENDED);
  }

  void markAsSuspended() {
    state = state | STATE_SUSPENDED;
  }

  void markAsRunnable() {
    state = state | STATE_RUNNABLE;
  }

  /// Runs this task, if it is ready to be run, and returns the next
  /// task to run.
  TaskControlBlock? run() {
    Packet? packet;
    if (state == STATE_SUSPENDED_RUNNABLE) {
      packet = queue;
      queue = packet!.link;
      state = queue == null ? STATE_RUNNING : STATE_RUNNABLE;
    } else {
      packet = null;
    }
    return task.run(packet);
  }

  /// Adds a packet to the worklist of this block's task, marks this as
  /// runnable if necessary, and returns the next runnable object to run
  /// (the one with the highest priority).
  TaskControlBlock checkPriorityAdd(TaskControlBlock task, Packet packet) {
    if (queue == null) {
      queue = packet;
      markAsRunnable();
      if (priority > task.priority) return this;
    } else {
      queue = packet.addTo(queue);
    }
    return task;
  }

  @override
  String toString() => 'tcb { $task@$state }';
}

///  Abstract task that manipulates work packets.
abstract class Task {
  Scheduler scheduler; // The scheduler that manages this task.

  Task(this.scheduler);

  TaskControlBlock? run(Packet? packet);
}

/// An idle task doesn't do any work itself but cycles control between the two
/// device tasks.
class IdleTask extends Task {
  int v1; // A seed value that controls how the device tasks are scheduled.
  int count; // The number of times this task should be scheduled.

  IdleTask(Scheduler scheduler, this.v1, this.count) : super(scheduler);

  @override
  TaskControlBlock? run(Packet? packet) {
    count--;
    if (count == 0) return scheduler.holdCurrent();
    if ((v1 & 1) == 0) {
      v1 = v1 >> 1;
      return scheduler.release(Richards.ID_DEVICE_A);
    }
    v1 = (v1 >> 1) ^ 0xD008;
    return scheduler.release(Richards.ID_DEVICE_B);
  }

  @override
  String toString() => 'IdleTask';
}

/// A task that suspends itself after each time it has been run to simulate
/// waiting for data from an external device.
class DeviceTask extends Task {
  Packet? v1;

  DeviceTask(Scheduler scheduler) : super(scheduler);

  @override
  TaskControlBlock? run(Packet? packet) {
    if (packet == null) {
      if (v1 == null) return scheduler.suspendCurrent();
      final Packet v = v1!;
      v1 = null;
      return scheduler.queue(v);
    }
    v1 = packet;
    return scheduler.holdCurrent();
  }

  @override
  String toString() => 'DeviceTask';
}

/// A task that manipulates work packets.
class WorkerTask extends Task {
  int v1; // A seed used to specify how work packets are manipulated.
  int v2; // Another seed used to specify how work packets are manipulated.

  WorkerTask(Scheduler scheduler, this.v1, this.v2) : super(scheduler);

  @override
  TaskControlBlock? run(Packet? packet) {
    if (packet == null) {
      return scheduler.suspendCurrent();
    }
    if (v1 == Richards.ID_HANDLER_A) {
      v1 = Richards.ID_HANDLER_B;
    } else {
      v1 = Richards.ID_HANDLER_A;
    }
    packet.id = v1;
    packet.a1 = 0;
    for (int i = 0; i < Richards.DATA_SIZE; i++) {
      v2++;
      if (v2 > 26) v2 = 1;
      packet.a2[i] = v2;
    }
    return scheduler.queue(packet);
  }

  @override
  String toString() => 'WorkerTask';
}

/// A task that manipulates work packets and then suspends itself.
class HandlerTask extends Task {
  Packet? v1;
  Packet? v2;

  HandlerTask(Scheduler scheduler) : super(scheduler);

  @override
  TaskControlBlock? run(Packet? packet) {
    if (packet != null) {
      if (packet.kind == Richards.KIND_WORK) {
        v1 = packet.addTo(v1);
      } else {
        v2 = packet.addTo(v2);
      }
    }
    if (v1 != null) {
      final int count = v1!.a1;
      if (count < Richards.DATA_SIZE) {
        if (v2 != null) {
          final Packet v = v2!;
          v2 = v.link;
          v.a1 = v1!.a2[count];
          v1!.a1 = count + 1;
          return scheduler.queue(v);
        }
      } else {
        final Packet v = v1!;
        v1 = v.link;
        return scheduler.queue(v);
      }
    }
    return scheduler.suspendCurrent();
  }

  @override
  String toString() => 'HandlerTask';
}

/// A simple package of data that is manipulated by the tasks.  The exact layout
/// of the payload data carried by a packet is not important, and neither is
/// the nature of the work performed on packets by the tasks. Besides carrying
/// data, packets form linked lists and are hence used both as data and
/// worklists.
class Packet {
  Packet? link; // The tail of the linked list of packets.
  int id; // An ID for this packet.
  int kind; // The type of this packet.
  int a1 = 0;

  List<int> a2 = List<int>.filled(Richards.DATA_SIZE, 0);

  Packet(this.link, this.id, this.kind);

  /// Add this packet to the end of a worklist, and return the worklist.
  Packet addTo(Packet? queue) {
    link = null;
    if (queue == null) return this;
    Packet? peek;
    Packet next = queue;
    while ((peek = next.link) != null) {
      next = peek!;
    }
    next.link = this;
    return queue;
  }

  @override
  String toString() => 'Packet';
}
