Created
June 28, 2020 06:51
-
-
Save weihsiu/b73612f6a5b3a8f10e06cd0800648a03 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package hellodotty | |
import java.util.concurrent.LinkedTransferQueue | |
import scala.collection._ | |
import scala.concurrent.ExecutionContext | |
import scala.reflect.ClassTag | |
object Actors: | |
trait Channel[A]: | |
def read: A | |
def write(x: A): Unit | |
object Channel: | |
def apply[A]: Channel[A] = new Channel[A]: | |
private val queue = LinkedTransferQueue[A]() | |
def read: A = queue.take | |
def write(x: A) = queue.put(x) | |
@FunctionalInterface | |
trait Receive[A] extends Function1[A, Receive[A]] | |
// https://twitter.com/li_haoyi/status/1169178929963229184?s=20 | |
trait Actor[M](using ec: ExecutionContext): | |
private val msgs = mutable.Queue[M]() | |
private var scheduled = false | |
private var recv: Receive[M] = _ | |
def receive: Receive[M] | |
def send(msg: M): Unit = synchronized: | |
msgs.enqueue(msg) | |
if !scheduled then | |
scheduled = true | |
ec.execute(() => dispatch()) | |
private def dispatch(): Unit = | |
val ms = synchronized(msgs.dequeueAll(_ => true)) | |
try recv = ms.foldLeft(if recv == null then receive else recv)(_(_)) | |
catch (e: Throwable) => e.printStackTrace | |
synchronized: | |
if msgs.nonEmpty | |
then ec.execute(() => dispatch()) | |
else scheduled = false | |
object Actor: | |
class ChannelActor[A](using ec: ExecutionContext) extends Actor[A]: | |
private val channel = Channel[A] | |
def read: A = channel.read | |
val receive = m => | |
channel.write(m) | |
receive | |
def main(args: Array[String]): Unit = | |
import scala.concurrent.ExecutionContext.Implicits.global | |
def go1(m: Int | String): Receive[Int | String] = | |
m match | |
case n: Int => | |
println(s"go1 int $n") | |
case s: String => | |
println(s"go1 str $s") | |
go1 | |
def go2(m: Double): Receive[Double] = | |
println(s"go2 double $m") | |
go2 | |
def [A, B](f: Receive[A]) ~ (g: Receive[B]): Receive[A | B] = ??? | |
val actor = new Actor[Int | Double | String]: | |
val receive = go1 ~ go2 | |
actor.send(123) | |
actor.send("hello") | |
actor.send(3.14) | |
io.StdIn.readLine |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment