<commit_before>package rescala.propagation

import java.lang.{Boolean => jlBool}

import rescala.graph.Reactive
import rescala.turns.Turn

import scala.collection.SortedSet

class LevelQueue(evaluator: Reactive => Unit)(implicit val currenTurn: Turn) {

  private var evalQueue = SortedSet[QueueElement]()

  /** mark the reactive as needing a reevaluation */
  def enqueue(minLevel: Int, needsEvaluate: Boolean = true)(dep: Reactive): Unit = {
    evalQueue += QueueElement(dep.level.get, dep, minLevel, needsEvaluate)
  }

  def remove(reactive: Reactive): Unit = {
    evalQueue = evalQueue.filter(qe => qe.reactive ne reactive)
  }

  final def evaluate(queueElement: QueueElement): Unit = {
    val QueueElement(headLevel, head, headMinLevel, doEvaluate) = queueElement
    if (headLevel < headMinLevel) {
      head.level.set(headMinLevel)
      val reevaluate = if (doEvaluate) true
      else if (evalQueue.isEmpty) false
      else if (evalQueue.head.reactive ne head) false
      else {
        evalQueue = evalQueue.tail
        true
      }
      enqueue(headMinLevel, reevaluate)(head)
      head.dependants.get.foreach(enqueue(headMinLevel + 1, needsEvaluate = false))
    }
    else if (doEvaluate) {
      evaluator(head)
    }
  }

  /** Evaluates all the elements in the queue */
  def evaluateQueue() = {
    while (evalQueue.nonEmpty) {
      val head = evalQueue.head
      evalQueue = evalQueue.tail
      evaluate(head)
    }
  }

  def clear() = evalQueue = SortedSet[QueueElement]()

  private case class QueueElement(level: Int, reactive: Reactive, minLevel: Int, needsEvaluate: Boolean)
  private implicit def ordering: Ordering[QueueElement] = new Ordering[QueueElement] {
    override def compare(x: QueueElement, y: QueueElement): Int = {
      val levelDiff = Integer.compare(x.level, y.level)
      if (levelDiff != 0) levelDiff
      else {
        val hashDiff = Integer.compare(x.reactive.hashCode, y.reactive.hashCode)
        if (hashDiff != 0) hashDiff
        else jlBool.compare(x.needsEvaluate, y.needsEvaluate)
      }
    }
  }
}
<commit_msg>clean level queue a bit<commit_after>package rescala.propagation

import java.lang.{Boolean => jlBool}

import rescala.graph.Reactive
import rescala.propagation.LevelQueue.QueueElement
import rescala.turns.Turn

import scala.collection.SortedSet

class LevelQueue()(implicit val currenTurn: Turn) {

  private var elements = SortedSet[QueueElement]()

  /** mark the reactive as needing a reevaluation */
  def enqueue(minLevel: Int, needsEvaluate: Boolean = true)(dep: Reactive): Unit = {
    elements += QueueElement(dep.level.get, dep, minLevel, needsEvaluate)
  }

  def remove(reactive: Reactive): Unit = {
    elements = elements.filter(qe => qe.reactive ne reactive)
  }

  final def handleHead(queueElement: QueueElement, evaluator: Reactive => Unit): Unit = {
    val QueueElement(headLevel, head, headMinLevel, doEvaluate) = queueElement
    if (headLevel < headMinLevel) {
      head.level.set(headMinLevel)
      val reevaluate = if (doEvaluate) true
      else if (elements.isEmpty) false
      else if (elements.head.reactive ne head) false
      else {
        elements = elements.tail
        true
      }
      enqueue(headMinLevel, reevaluate)(head)
      head.dependants.get.foreach(enqueue(headMinLevel + 1, needsEvaluate = false))
    }
    else if (doEvaluate) {
      evaluator(head)
    }
  }

  /** Evaluates all the elements in the queue */
  def evaluateQueue(evaluator: Reactive => Unit) = {
    while (elements.nonEmpty) {
      val head = elements.head
      elements = elements.tail
      handleHead(head, evaluator)
    }
  }

  def clear() = elements = SortedSet[QueueElement]()

}

object LevelQueue {

  def apply() = new LevelQueue()

  private case class QueueElement(level: Int, reactive: Reactive, minLevel: Int, needsEvaluate: Boolean)
  private implicit def ordering: Ordering[QueueElement] = new Ordering[QueueElement] {
    override def compare(x: QueueElement, y: QueueElement): Int = {
      val levelDiff = Integer.compare(x.level, y.level)
      if (levelDiff != 0) levelDiff
      else {
        val hashDiff = Integer.compare(x.reactive.hashCode, y.reactive.hashCode)
        if (hashDiff != 0) hashDiff
        else jlBool.compare(x.needsEvaluate, y.needsEvaluate)
      }
    }
  }
}

{'fraction_non_alphanumeric': 0.10347222222222222, 'fraction_numerical': 0.001388888888888889, 'mean_word_length': 3.395727365208545, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3010675', 'n_tokens_mistral': 1368, 'n_tokens_neox': 1299, 'n_words': 338}