Init
This commit is contained in:
commit
26f5bf3c3e
12 changed files with 263 additions and 0 deletions
68
src/main/scala/Gen.scala
Normal file
68
src/main/scala/Gen.scala
Normal file
|
@ -0,0 +1,68 @@
|
|||
package gen
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
object Gen:
|
||||
import scala.scalanative.runtime.Continuations.*
|
||||
enum Seqn[+T] {
|
||||
case Empty
|
||||
case Next(t: T, nx: () => Seqn[T])
|
||||
}
|
||||
|
||||
type CanGen[-T] = BoundaryLabel[Seqn[T]]
|
||||
|
||||
def apply[T](f: CanGen[T] ?=> Unit): Iterator[T] =
|
||||
new Iterator[T] {
|
||||
var buf = boundary { f; Seqn.Empty }
|
||||
|
||||
def hasNext: Boolean = buf != Seqn.Empty
|
||||
|
||||
def next() = buf match
|
||||
case Seqn.Empty => ???
|
||||
case Seqn.Next(t, nx) =>
|
||||
buf = nx()
|
||||
t
|
||||
}
|
||||
|
||||
def put[T](value: T)(using CanGen[T]): Unit =
|
||||
suspend[Seqn[T]](f => Seqn.Next(value, f))
|
||||
end Gen
|
||||
|
||||
import Gen.*
|
||||
|
||||
def allRightTriangles = Gen {
|
||||
var c = 1
|
||||
var a = 1
|
||||
var b = 1
|
||||
|
||||
def nextState() =
|
||||
if (a * a + b * b > c * c) then
|
||||
a += 1
|
||||
b = a
|
||||
if (a >= c) then
|
||||
c += 1
|
||||
a = 1
|
||||
b = 1
|
||||
else b += 1
|
||||
|
||||
def toOk() =
|
||||
while a * a + b * b != c * c do nextState()
|
||||
|
||||
while (true) do
|
||||
toOk()
|
||||
put((a, b, c))
|
||||
nextState()
|
||||
}
|
||||
|
||||
def fibonacci = Gen {
|
||||
@tailrec def go(a: Int, b: Int): Unit =
|
||||
put(a)
|
||||
go(b, (a + b))
|
||||
go(1, 1)
|
||||
}
|
||||
|
||||
def rightTriangles(upTo: Int) = Gen {
|
||||
allRightTriangles
|
||||
.takeWhile((_, _, c) => c <= upTo)
|
||||
.foreach(put)
|
||||
}
|
52
src/main/scala/Main.scala
Normal file
52
src/main/scala/Main.scala
Normal file
|
@ -0,0 +1,52 @@
|
|||
import gen.rightTriangles
|
||||
import concurrent.simple.*
|
||||
import gen.fibonacci
|
||||
|
||||
object Test {
|
||||
def main(args: Array[String]): Unit =
|
||||
testGen()
|
||||
testGenCompare()
|
||||
// testSimpleFutures()
|
||||
|
||||
def testGen(): Unit =
|
||||
// println(rightTriangles(1500).toList)
|
||||
println(fibonacci.take(1000).toList)
|
||||
|
||||
def testGenCompare(): Unit =
|
||||
val iter = new Iterator[(Int, Int, Int)] {
|
||||
var c = 1
|
||||
var a = 1
|
||||
var b = 1
|
||||
|
||||
def nextState() =
|
||||
if (a * a + b * b > c * c) then
|
||||
a += 1
|
||||
b = a
|
||||
if (a >= c) then
|
||||
c += 1
|
||||
a = 1
|
||||
b = 1
|
||||
else b += 1
|
||||
|
||||
def toOk() =
|
||||
while a * a + b * b != c * c do nextState()
|
||||
|
||||
def hasNext =
|
||||
toOk()
|
||||
c <= 1500
|
||||
|
||||
def next() =
|
||||
toOk()
|
||||
val res = (a, b, c)
|
||||
nextState()
|
||||
res
|
||||
}
|
||||
println(iter.toList)
|
||||
|
||||
def testSimpleFutures(): Unit =
|
||||
val futures = (1 to 10000)
|
||||
.map(i => Future { i.toLong })
|
||||
val futSq = futures.map(f => Future { f.await * f.await })
|
||||
val sum = Future { futSq.map(_.await).sum }
|
||||
println(Scheduler.blocking { sum.await })
|
||||
}
|
95
src/main/scala/concurrent/simple/simple-futures.scala
Normal file
95
src/main/scala/concurrent/simple/simple-futures.scala
Normal file
|
@ -0,0 +1,95 @@
|
|||
package concurrent.simple
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
import scala.scalanative.runtime.Continuations.{boundary, suspend}
|
||||
import scala.scalanative.unsafe.Tag
|
||||
import scala.collection.mutable.ArrayDeque
|
||||
import scala.annotation.tailrec
|
||||
|
||||
/* A single threaded scheduler */
|
||||
object Scheduler:
|
||||
private val taskQueue = ArrayDeque[Runnable]()
|
||||
|
||||
def schedule(task: Runnable): Unit =
|
||||
synchronized {
|
||||
taskQueue.addOne(task)
|
||||
notify()
|
||||
}
|
||||
|
||||
def nextTask(): Option[Runnable] = synchronized {
|
||||
if taskQueue.isEmpty then None
|
||||
else Some(taskQueue.removeLast())
|
||||
}
|
||||
|
||||
def blocking[T](f: Async ?=> T): T =
|
||||
var result: Option[T] = None
|
||||
schedule(() => {
|
||||
Future.async {
|
||||
val v = f;
|
||||
synchronized { result = Some(v); notifyAll() }
|
||||
}
|
||||
})
|
||||
|
||||
// spawn a bunch of threads
|
||||
for (i <- 2 to 8) do
|
||||
Thread
|
||||
.ofPlatform()
|
||||
.start(() =>
|
||||
println(s"starting thread $i")
|
||||
next(synchronized { result.isDefined })
|
||||
)
|
||||
|
||||
next(synchronized { result.isDefined })
|
||||
result.get
|
||||
|
||||
@tailrec private def next(condition: => Boolean): Unit =
|
||||
if condition then ()
|
||||
else
|
||||
nextTask() match
|
||||
case None => synchronized { if !condition then wait() }
|
||||
case Some(value) => value.run()
|
||||
next(condition)
|
||||
|
||||
trait Async:
|
||||
def await[T](f: Future[T]): T
|
||||
|
||||
class Future[+T](body: Async ?=> T):
|
||||
private var result: Option[T] = None
|
||||
private var waiting: ListBuffer[T => Unit] = ListBuffer()
|
||||
private def addWaiting(k: T => Unit): Unit = waiting += k
|
||||
|
||||
def await(using a: Async): T = a.await(this)
|
||||
|
||||
private def complete(): Unit =
|
||||
Future.async {
|
||||
val value = body
|
||||
result = Some(value)
|
||||
for k <- waiting do Scheduler.schedule(() => k(value))
|
||||
waiting.clear()
|
||||
}
|
||||
|
||||
Scheduler.schedule(() => complete())
|
||||
|
||||
object Future:
|
||||
// a handler for Async
|
||||
def async(body: Async ?=> Unit): Unit =
|
||||
boundary[Unit] {
|
||||
given Async with {
|
||||
def await[T](f: Future[T]): T =
|
||||
try {
|
||||
f.result match
|
||||
case Some(x) => x
|
||||
case None => suspend[T, Unit](s => f.addWaiting(s))
|
||||
} catch
|
||||
case (e: Exception) => {
|
||||
println(e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
body
|
||||
}
|
||||
end Future
|
||||
|
||||
// def Test(x: Future[Int], xs: List[Future[Int]]) =
|
||||
// Future:
|
||||
// x.await + xs.map(_.await).sum
|
Loading…
Add table
Add a link
Reference in a new issue