All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.joern.x2cpg.utils.ConcurrentTaskUtil.scala Maven / Gradle / Ivy

There is a newer version: 4.0.131
Show newest version
package io.joern.x2cpg.utils

import java.util
import java.util.concurrent.{Callable, Executors}
import java.util.stream.{Collectors, StreamSupport}
import java.util.{Collections, Spliterator, Spliterators}
import scala.jdk.CollectionConverters.*
import scala.util.Try

/** A utility for providing out-of-the-box basic concurrent execution for a collection of Scala functions.
  */
object ConcurrentTaskUtil {

  private val MAX_POOL_SIZE = Runtime.getRuntime.availableProcessors()

  /** Uses a thread pool with a limited number of active threads executing a task at any given point. This is effective
    * when tasks may require large amounts of memory, or single tasks are too short lived.
    *
    * @param tasks
    *   the tasks to parallelize.
    * @param maxPoolSize
    *   the max pool size to allow for active threads.
    * @tparam V
    *   the output type of each task.
    * @return
    *   an array of the executed tasks as either a success or failure.
    */
  def runUsingThreadPool[V](tasks: Iterator[() => V], maxPoolSize: Int = MAX_POOL_SIZE): List[Try[V]] = {
    val ex = Executors.newFixedThreadPool(maxPoolSize)
    try {
      val callables = Collections.list(tasks.map { x =>
        new Callable[V] {
          override def call(): V = x.apply()
        }
      }.asJavaEnumeration)
      ex.invokeAll(callables).asScala.map(x => Try(x.get())).toList
    } finally {
      ex.shutdown()
    }
  }

  /** Uses a Spliterator to run a number of tasks in parallel, where any number of threads may be alive at any point.
    * This is useful for running a large number of tasks with low memory consumption. Spliterator's default thread pool
    * is ForkJoinPool.commonPool().
    *
    * @param tasks
    *   the tasks to parallelize.
    * @tparam V
    *   the output type of each task.
    * @return
    *   an array of the executed tasks as either a success or failure.
    */
  def runUsingSpliterator[V](tasks: Iterator[() => V]): Seq[Try[V]] = {
    scala.collection.immutable.ArraySeq
      .ofRef(
        java.util.Arrays
          .stream(tasks.toArray)
          .parallel()
          .map(task => Try(task.apply()))
          .toArray
      )
      .asInstanceOf[scala.collection.immutable.ArraySeq[Try[V]]]
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy