Skip to content

Instantly share code, notes, and snippets.

@weihsiu
Created June 28, 2020 06:51
Show Gist options
  • Save weihsiu/b73612f6a5b3a8f10e06cd0800648a03 to your computer and use it in GitHub Desktop.
Save weihsiu/b73612f6a5b3a8f10e06cd0800648a03 to your computer and use it in GitHub Desktop.
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