Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Future's Flatmap is not stacksafe #11256

Closed
He-Pin opened this issue Nov 15, 2018 · 11 comments
Closed

Future's Flatmap is not stacksafe #11256

He-Pin opened this issue Nov 15, 2018 · 11 comments

Comments

@He-Pin
Copy link
Contributor

He-Pin commented Nov 15, 2018

@RunWith(classOf[JUnit4])
class Stacksafe {

  @Test
  def testFib(): Unit = {
    implicit val ex: ExecutionContext = new ExecutionContext {
      override def execute(runnable: Runnable): Unit = runnable.run()
      override def reportFailure(cause: Throwable): Unit = cause.printStackTrace()
    }

    def fib(n: Int, a: Long = 0, b: Long = 1): Future[Long] =
      Future(a + b).flatMap { b2 =>
        if (n > 0)
          fib(n - 1, b, b2)
        else
          Future(b2)
      }

    val future = fib(1000)
    println(Await.result(future,Duration.Inf))
  }
}

It's ok with 100,but not 1000

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 15, 2018

#6932

@viktorklang
Copy link

This is not a bug. Your Execution context is not stack safe.

@viktorklang
Copy link

Think of ExecutionContext as the Interpreter, where the "next actions" enter through execute and execution of the Runnable can lead to more calls to execute. Therefor it is the responsibility of the implementor of ExecutionContext to make sure that it is stack safe / reentrant.

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 15, 2018

@viktorklang I try this because of Task or IO claims they are, so I take a try. I think to fix this will change so much, may not worth it.

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 15, 2018

This is not a bug. Your Execution context is not stack safe.

Seems it's by design:)

@viktorklang
Copy link

Task/IO are only stacksafe when their interpreters are stack safe. This is also true for Future. For some examples on how to make stacksafe ExecutionContexts, look at: https://github.com/scala/scala/blob/2.13.x/src/library/scala/concurrent/BatchingExecutor.scala which is used by this. :)

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 15, 2018

thanks, I was expecting it will be safe in any way.

@He-Pin He-Pin closed this as completed Nov 15, 2018
@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 15, 2018

@viktorklang So,now anyone want to make it safe then will need to take care of the Batchable:)

@viktorklang
Copy link

@hepin1989 Not necessarily :) Most thread pools are stack safe by definition since they add new Runnables to a queue. (just like the BatchingExecutor does).

@He-Pin
Copy link
Contributor Author

He-Pin commented Nov 15, 2018

@viktorklang But I do expect even I call runnable.run directly, it works too.

@viktorklang
Copy link

@hepin1989

A general purpose ExecutionContext must be asynchronous in executing any Runnable that is passed into its execute-method. A special purpose ExecutionContext may be synchronous but must only be passed to code that is explicitly safe to be run using a synchronously executing ExecutionContext.
--https://www.scala-lang.org/api/current/scala/concurrent/ExecutionContext.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants