Skip to content

Commit 401bb6d

Browse files
committed
Cancellable workaround
1 parent d61b1c1 commit 401bb6d

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

jvm/src/main/scala/async/VThreadSupport.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import java.lang.invoke.{MethodHandles, VarHandle}
66
import java.util.concurrent.locks.ReentrantLock
77
import scala.annotation.unchecked.uncheckedVariance
88
import scala.concurrent.duration.FiniteDuration
9+
import scala.annotation.constructorOnly
910

1011
object VThreadScheduler extends Scheduler:
1112
private val VTFactory = Thread
@@ -21,7 +22,7 @@ object VThreadScheduler extends Scheduler:
2122
val sr = ScheduledRunnable(delay, body)
2223
() => sr.cancel()
2324

24-
private class ScheduledRunnable(val delay: FiniteDuration, val body: Runnable^) extends Cancellable {
25+
private class ScheduledRunnable(delay: FiniteDuration, body: Runnable^) extends Cancellable {
2526
@volatile var interruptGuard = true // to avoid interrupting the body
2627

2728
val th = VTFactory.newThread: () =>

shared/src/main/scala/async/Cancellable.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package gears.async
22

3+
import language.experimental.captureChecking
4+
5+
import java.util.concurrent.atomic.AtomicLong
6+
37
/** A trait for cancellable entities that can be grouped. */
48
trait Cancellable:
5-
9+
val id = Cancellable.Id()
610
private var group: CompletionGroup = CompletionGroup.Unlinked
711

812
/** Issue a cancel request */
@@ -28,6 +32,11 @@ trait Cancellable:
2832
end Cancellable
2933

3034
object Cancellable:
35+
opaque type Id = Long
36+
private object Id:
37+
private val gen = AtomicLong(0)
38+
def apply(): Id = gen.incrementAndGet()
39+
3140
/** A special [[Cancellable]] object that just tracks whether its linked group was cancelled. */
3241
trait Tracking extends Cancellable:
3342
def isCancelled: Boolean

shared/src/main/scala/async/CompletionGroup.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package gears.async
2+
import language.experimental.captureChecking
3+
24
import scala.collection.mutable
35
import scala.util.Success
46

57
import Future.Promise
8+
import scala.annotation.unchecked.uncheckedCaptures
69

710
/** A group of cancellable objects that are completed together. Cancelling the group means cancelling all its
811
* uncompleted members.
912
*/
1013
class CompletionGroup extends Cancellable.Tracking:
11-
private val members: mutable.Set[Cancellable] = mutable.Set()
14+
private val members: mutable.Set[(Cancellable^) @uncheckedCaptures] = mutable.Set[(Cancellable^) @uncheckedCaptures]()
1215
private var canceled: Boolean = false
1316
private var cancelWait: Option[Promise[Unit]] = None
1417

@@ -29,14 +32,14 @@ class CompletionGroup extends Cancellable.Tracking:
2932
unlink()
3033

3134
/** Add given member to the members set. If the group has already been cancelled, cancels that member immediately. */
32-
def add(member: Cancellable): Unit =
35+
def add(member: Cancellable^): Unit =
3336
val alreadyCancelled = synchronized:
3437
members += member // Add this member no matter what since we'll wait for it still
3538
canceled
3639
if alreadyCancelled then member.cancel()
3740

3841
/** Remove given member from the members set if it is an element */
39-
def drop(member: Cancellable): Unit = synchronized:
42+
def drop(member: Cancellable^): Unit = synchronized:
4043
members -= member
4144
if members.isEmpty && cancelWait.isDefined then cancelWait.get.complete(Success(()))
4245

@@ -50,8 +53,8 @@ object CompletionGroup:
5053
object Unlinked extends CompletionGroup:
5154
override def cancel(): Unit = ()
5255
override def waitCompletion()(using Async): Unit = ()
53-
override def add(member: Cancellable): Unit = ()
54-
override def drop(member: Cancellable): Unit = ()
56+
override def add(member: Cancellable^): Unit = ()
57+
override def drop(member: Cancellable^): Unit = ()
5558
end Unlinked
5659

5760
end CompletionGroup

0 commit comments

Comments
 (0)