Skip to content

Commit

Permalink
Futures interface with await (#112)
Browse files Browse the repository at this point in the history
Simple direct-style futures using threads that are observationally pure
  • Loading branch information
vkuncak authored Oct 11, 2024
1 parent b209422 commit bae9a88
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions tutorials/futures/PossibleFutures.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import stainless.annotation.*
import stainless.lang.*
import stainless.lang.StaticChecks.*

object PossibleFutures:

// constructure is private: enforce using Future.apply and hence asynchrony
class Future[A](private val todo : () => A):
@ghost
def expected: A = todo() // predicted value. Public, but spec only

def await: A = {
todo()
}.ensuring(_ == expected)

object Future:
@extern
def apply[A](todo: () => A): Future[A] = {
var result: Option[A] = None[A]()
val t = new Thread:
override def run: Unit =
result = Some(todo())
println(f"Computed $result")

t.start
def expandedTodo: A =
t.join
result.get

new Future[A](() => expandedTodo)
}.ensuring(_.expected == todo())

def small(x:Int): Boolean =
-128 <= x && x < 127

@extern
def sleep(t: Int): Unit =
Thread.sleep(scala.util.Random.nextInt(t))

def slow(x: Int): Int =
sleep(100)
x

def addThree(x: Future[Int]) =
require(small(x.expected))
val two = Future(() => slow(1))
val one = Future(() => slow(2))
one.await + two.await + x.await

// run to observe that values are computed asynchronously
@main @extern
def test =
println(f"The result is: ${addThree(Future(() => slow(100)))}")

0 comments on commit bae9a88

Please sign in to comment.