Skip to content

Commit 67e70e3

Browse files
committed
Add CSP-style coroutines that communicate with channels
1 parent ad18fcf commit 67e70e3

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

tests/pos/suspend-strawman-2/channels.scala

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package concurrent
22
import scala.collection.mutable, mutable.ListBuffer
3-
import scala.util.boundary.Label
3+
import scala.util.boundary, boundary.Label
44
import runtime.suspend
5+
import java.util.concurrent.CancellationException
56
import Async.{Listener, await}
67

78
/** An unbounded asynchronous channel. Senders do not wait for matching
@@ -96,6 +97,40 @@ object SyncChannel:
9697

9798
end SyncChannel
9899

100+
/** A simplistic coroutine. Error handling is still missing, */
101+
class Coroutine(body: Async ?=> Unit)(using scheduler: Scheduler) extends Cancellable:
102+
private var children: mutable.ListBuffer[Cancellable] = mutable.ListBuffer()
103+
@volatile var cancelled = false
104+
105+
def cancel() =
106+
cancelled = true
107+
synchronized(children).foreach(_.cancel())
108+
109+
def addChild(child: Cancellable) = synchronized:
110+
children += child
111+
112+
boundary [Unit]:
113+
given Async = new Async.Impl(this, scheduler):
114+
def checkCancellation() =
115+
if cancelled then throw new CancellationException()
116+
try body
117+
catch case ex: CancellationException => ()
118+
end Coroutine
119+
120+
def TestChannel(using Scheduler) =
121+
val c = SyncChannel[Option[Int]]()
122+
Coroutine:
123+
for i <- 0 to 100 do
124+
c.send(Some(i))
125+
c.send(None)
126+
Coroutine:
127+
var sum = 0
128+
def loop(): Unit =
129+
c.read() match
130+
case Some(x) => sum += x; loop()
131+
case None => println(sum)
132+
loop()
133+
99134
def TestRace =
100135
val c1, c2 = SyncChannel[Int]()
101136
val s = c1.canSend
@@ -114,3 +149,4 @@ def TestRace =
114149
.map:
115150
case Left(x) => -x
116151
case Right(x) => x
152+

0 commit comments

Comments
 (0)