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

monix.execution.internal.Platform.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2014-2019 by The Monix Project Developers.
 * See the project homepage at: https://monix.io
 *
 * 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 monix.execution.internal

import monix.execution.schedulers.CanBlock

import scala.concurrent.{Await, Awaitable}
import scala.concurrent.duration.Duration
import scala.util.Try

private[monix] object Platform {
  /**
    * Returns `true` in case Monix is running on top of Scala.js,
    * or `false` otherwise.
    */
  final val isJS = false

  /**
    * Returns `true` in case Monix is running on top of the JVM,
    * or `false` otherwise.
    */
  final val isJVM = true

  /** Recommended batch size used for breaking synchronous loops in
    * asynchronous batches. When streaming value from a producer to
    * a synchronous consumer it's recommended to break the streaming
    * in batches as to not hold the current thread or run-loop
    * indefinitely.
    *
    * Rounding up to the closest power of 2, because then for
    * applying the modulo operation we can just do:
    * {{{
    *   val modulus = Platform.recommendedBatchSize - 1
    *   // ...
    *   nr = (nr + 1) & modulus
    * }}}
    *
    * Can be configured by setting Java properties:
    *
    * 
    *   java -Dmonix.environment.batchSize=256 \
    *        ...
    * 
*/ val recommendedBatchSize: Int = { Option(System.getProperty("monix.environment.batchSize", "")) .filter(s => s != null && s.nonEmpty) .flatMap(s => Try(s.toInt).toOption) .map(math.nextPowerOf2) .getOrElse(1024) } /** Recommended chunk size in unbounded buffer implementations that are chunked, * or in chunked streaming. * * Examples: * * - the default when no `chunkSizeHint` is specified in * [[monix.execution.BufferCapacity.Unbounded BufferCapacity.Unbounded]] * - the chunk size used in * [[monix.reactive.OverflowStrategy.Unbounded OverflowStrategy.Unbounded]] * - the default in * [[monix.tail.Iterant.fromConsumer Iterant.fromConsumer]] or in * [[monix.tail.Iterant.fromConsumer Iterant.fromChannel]] * * Can be configured by setting Java properties: * *
    *   java -Dmonix.environment.bufferChunkSize=128 \
    *        ...
    * 
* * Should be a power of 2 or it gets rounded to one. */ val recommendedBufferChunkSize: Int = { Option(System.getProperty("monix.environment.bufferChunkSize", "")) .filter(s => s != null && s.nonEmpty) .flatMap(s => Try(s.toInt).toOption) .map(math.nextPowerOf2) .getOrElse(256) } /** Default value for auto cancelable loops, set to `false`. * * On top of the JVM the default can be overridden by setting the following * system property: * * `monix.environment.autoCancelableRunLoops` * * You can set the following values: * * - `true`, `yes` or `1` for enabling (the default) * - `no`, `false` or `0` for disabling * * NOTE: this values was `false` by default prior to the Monix 3.0.0 * release. This changed along with the release of Cats-Effect 1.1.0 * which now recommends for this default to be `true` due to the design * of its type classes. */ val autoCancelableRunLoops: Boolean = { Option(System.getProperty("monix.environment.autoCancelableRunLoops", "")) .map(_.toLowerCase) .forall(v => v != "no" && v != "false" && v != "0") } /** * Default value for local context propagation loops is set to * false. On top of the JVM the default can be overridden by * setting the following system property: * * - `monix.environment.localContextPropagation` * (`true`, `yes` or `1` for enabling) */ val localContextPropagation: Boolean = Option(System.getProperty("monix.environment.localContextPropagation", "")) .map(_.toLowerCase) .exists(v => v == "yes" || v == "true" || v == "1") /** * Establishes the maximum stack depth for fused `.map` operations. * * The default is `128`, from which we subtract one as an * optimization. This default has been reached like this: * * - according to official docs, the default stack size on 32-bits * Windows and Linux was 320 KB, whereas for 64-bits it is 1024 KB * - according to measurements chaining `Function1` references uses * approximately 32 bytes of stack space on a 64 bits system; * this could be lower if "compressed oops" is activated * - therefore a "map fusion" that goes 128 in stack depth can use * about 4 KB of stack space * * If this parameter becomes a problem, it can be tuned by setting * the `monix.environment.fusionMaxStackDepth` environment variable when * executing the Java VM: * *
    *   java -Dmonix.environment.fusionMaxStackDepth=32 \
    *        ...
    * 
*/ val fusionMaxStackDepth = Option(System.getProperty("monix.environment.fusionMaxStackDepth")) .filter(s => s != null && s.nonEmpty) .flatMap(s => Try(s.toInt).toOption) .filter(_ > 0) .map(_ - 1) .getOrElse(127) /** Blocks for the result of `fa`. * * This operation is only supported on top of the JVM, whereas for * JavaScript a dummy is provided. */ def await[A](fa: Awaitable[A], timeout: Duration)(implicit permit: CanBlock): A = Await.result(fa, timeout) /** Composes multiple errors together, meant for those cases in which * error suppression, due to a second error being triggered, is not * acceptable. * * On top of the JVM this function uses `Throwable#addSuppressed`, * available since Java 7. On top of JavaScript the function would return * a `CompositeException`. */ def composeErrors(first: Throwable, rest: Throwable*): Throwable = { for (e <- rest; if e ne first) first.addSuppressed(e) first } /** Useful utility that combines an `Either` result, which is what * `MonadError#attempt` returns. */ def composeErrors(first: Throwable, second: Either[Throwable, _]): Throwable = second match { case Left(e2) if first ne e2 => first.addSuppressed(e2) first case _ => first } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy