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

monix.execution.CancelableFuture.scala Maven / Gradle / Ivy

/*
 * Copyright (c) 2014-2016 by its authors. Some rights reserved.
 * 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

import scala.concurrent._
import scala.concurrent.duration.Duration
import scala.reflect.ClassTag
import scala.util.{Failure, Success, Try}

/** Represents an asynchronous computation that can be canceled
  * as long as it isn't complete.
  */
trait CancelableFuture[+T] extends Future[T] with Cancelable {
  // Overriding methods for getting CancelableFuture in return

  override def failed: CancelableFuture[Throwable] =
    CancelableFuture(super.failed, this)
  override def transform[S](s: (T) => S, f: (Throwable) => Throwable)(implicit executor: ExecutionContext): CancelableFuture[S] =
    CancelableFuture(super.transform(s, f), this)
  override def map[S](f: (T) => S)(implicit executor: ExecutionContext): CancelableFuture[S] =
    CancelableFuture(super.map(f), this)
  override def flatMap[S](f: (T) => Future[S])(implicit executor: ExecutionContext): CancelableFuture[S] =
    CancelableFuture(super.flatMap(f), this)
  override def filter(p: (T) => Boolean)(implicit executor: ExecutionContext): CancelableFuture[T] =
    CancelableFuture(super.filter(p), this)
  override def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): CancelableFuture[S] =
    CancelableFuture(super.collect(pf), this)
  override def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): CancelableFuture[U] =
    CancelableFuture(super.recover(pf), this)
  override def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): CancelableFuture[U] =
    CancelableFuture(super.recoverWith(pf), this)
  override def zip[U](that: Future[U]): CancelableFuture[(T, U)] =
    CancelableFuture(super.zip(that), this)
  override def fallbackTo[U >: T](that: Future[U]): CancelableFuture[U] =
    CancelableFuture(super.fallbackTo(that), this)
  override def mapTo[S](implicit tag: ClassTag[S]): CancelableFuture[S] =
    CancelableFuture(super.mapTo(tag), this)
  override def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): CancelableFuture[T] =
    CancelableFuture(super.andThen(pf), this)

  // Needed for Scala 2.12 compatibility
  def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): CancelableFuture[S] =
    CancelableFuture(FutureUtils.transform(this, f), this)

  // Needed for Scala 2.12 compatibility
  def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): CancelableFuture[S] =
    CancelableFuture(FutureUtils.transformWith(this, f), this)
}

object CancelableFuture {
  /** Builder for a [[CancelableFuture]].
    *
    * @param underlying is an underlying `Future` reference that will respond to `onComplete` calls
    * @param cancelable is a [[monix.execution.Cancelable Cancelable]]
    *        that can be used to cancel the active computation
    */
  def apply[T](underlying: Future[T], cancelable: Cancelable): CancelableFuture[T] =
    new Implementation[T](underlying, cancelable)

  /** Promotes a strict `value` to a [[CancelableFuture]] that's already complete. */
  def successful[T](value: T): CancelableFuture[T] =
    new Now[T](Success(value))

  /** Promotes a strict `Throwable` to a [[CancelableFuture]] that's already complete. */
  def failed[T](ex: Throwable): CancelableFuture[T] =
    new Now[T](Failure(ex))

  /** An already completed [[CancelableFuture]]. */
  final val unit: CancelableFuture[Unit] =
    successful(())

  /** Returns a [[CancelableFuture]] instance that will never complete. */
  final def never[T]: CancelableFuture[T] =
    Never

  /** Promotes a strict `Try[T]` to a [[CancelableFuture]] that's already complete. */
  def fromTry[T](value: Try[T]): CancelableFuture[T] =
    value match {
      case Success(v) => successful(v)
      case Failure(ex) => failed(ex)
    }

  /** A [[CancelableFuture]] instance that will never complete. */
  private object Never extends CancelableFuture[Nothing] {
    def onComplete[U](f: (Try[Nothing]) => U)
      (implicit executor: ExecutionContext): Unit = ()

    val isCompleted = false
    val value = None

    @scala.throws[Exception](classOf[Exception])
    def result(atMost: Duration)(implicit permit: CanAwait): Nothing =
      throw new TimeoutException("This CancelableFuture will never finish!")

    @scala.throws[InterruptedException](classOf[InterruptedException])
    @scala.throws[TimeoutException](classOf[TimeoutException])
    def ready(atMost: Duration)(implicit permit: CanAwait): this.type =
      throw new TimeoutException("This CancelableFuture will never finish!")

    def cancel(): Unit = ()
  }

  /** An internal [[CancelableFuture]] implementation. */
  private final class Now[+T](immediate: Try[T]) extends CancelableFuture[T] {
    def ready(atMost: Duration)(implicit permit: CanAwait): this.type = this
    def result(atMost: Duration)(implicit permit: CanAwait): T = immediate.get

    def cancel(): Unit = ()
    def isCompleted: Boolean = true
    val value: Some[Try[T]] = Some(immediate)

    def onComplete[U](f: (Try[T]) => U)(implicit executor: ExecutionContext): Unit =
      executor.execute(new Runnable { def run(): Unit = f(immediate) })

    // Overriding methods for getting CancelableFuture in return
    override def failed: CancelableFuture[Throwable] =
      immediate match {
        case Success(_) => new Now(Failure(new NoSuchElementException("failed")))
        case Failure(ex) => new Now(Success(ex))
      }
  }

  /** An actual [[CancelableFuture]] implementation; internal. */
  private final class Implementation[+T](underlying: Future[T], cancelable: Cancelable)
    extends CancelableFuture[T] {

    override def onComplete[U](f: (Try[T]) => U)(implicit executor: ExecutionContext): Unit =
      underlying.onComplete(f)(executor)
    override def isCompleted: Boolean =
      underlying.isCompleted
    override def value: Option[Try[T]] =
      underlying.value

    @throws[Exception](classOf[Exception])
    def result(atMost: Duration)(implicit permit: CanAwait): T =
      underlying.result(atMost)(permit)

    @throws[InterruptedException](classOf[InterruptedException])
    @throws[TimeoutException](classOf[TimeoutException])
    def ready(atMost: Duration)(implicit permit: CanAwait): this.type = {
      underlying.ready(atMost)(permit)
      this
    }

    override def cancel(): Unit =
      cancelable.cancel()

    // Overriding methods for getting CancelableFuture in return
    override def failed: CancelableFuture[Throwable] =
      new Implementation(underlying.failed, cancelable)
    override def transform[S](s: (T) => S, f: (Throwable) => Throwable)(implicit executor: ExecutionContext): CancelableFuture[S] =
      new Implementation(underlying.transform(s, f), cancelable)
    override def map[S](f: (T) => S)(implicit executor: ExecutionContext): CancelableFuture[S] =
      new Implementation(underlying.map(f), cancelable)
    override def flatMap[S](f: (T) => Future[S])(implicit executor: ExecutionContext): CancelableFuture[S] =
      new Implementation(underlying.flatMap(f), cancelable)
    override def filter(p: (T) => Boolean)(implicit executor: ExecutionContext): CancelableFuture[T] =
      new Implementation(underlying.filter(p), cancelable)
    override def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): CancelableFuture[S] =
      new Implementation(underlying.collect(pf), cancelable)
    override def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): CancelableFuture[U] =
      new Implementation(underlying.recover(pf), cancelable)
    override def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): CancelableFuture[U] =
      new Implementation(underlying.recoverWith(pf), cancelable)
    override def zip[U](that: Future[U]): CancelableFuture[(T, U)] =
      new Implementation(underlying.zip(that), cancelable)
    override def fallbackTo[U >: T](that: Future[U]): CancelableFuture[U] =
      new Implementation(underlying.fallbackTo(that), cancelable)
    override def mapTo[S](implicit tag: ClassTag[S]): CancelableFuture[S] =
      new Implementation(underlying.mapTo[S], cancelable)
    override def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): CancelableFuture[T] =
      new Implementation(underlying.andThen(pf), cancelable)

    // Needed for Scala 2.12 compatibility
    override def transform[S](f: Try[T] => Try[S])
      (implicit executor: ExecutionContext): CancelableFuture[S] =
      new Implementation[S](FutureUtils.transform(underlying, f), cancelable)

    // Needed for Scala 2.12 compatibility
    override def transformWith[S](f: Try[T] => Future[S])
      (implicit executor: ExecutionContext): CancelableFuture[S] =
      new Implementation[S](FutureUtils.transformWith(underlying, f), cancelable)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy