!str,htc remove FlexiMerge/Route
- replace all occurrences with equivalent GraphStage implementations This commit introduces a mini-DSL for GraphStage that allows emitting or reading multiple elements to/from a port with one statement, installing stateful handlers on the port to make it work. The emitting side allows stacked continuations, meaning that while an emit() is ongoing (waiting for demand) another one can be added to the queue; this allows convenient formualation of merge-type stages.
This commit is contained in:
parent
dc07fd250c
commit
02810cfa64
45 changed files with 1001 additions and 3227 deletions
|
|
@ -18,8 +18,9 @@ object Merge {
|
|||
* Create a new `Merge` with the specified number of input ports.
|
||||
*
|
||||
* @param inputPorts number of input ports
|
||||
* @param eagerClose if true, the merge will complete as soon as one of its inputs completes.
|
||||
*/
|
||||
def apply[T](inputPorts: Int): Merge[T] = new Merge(inputPorts)
|
||||
def apply[T](inputPorts: Int, eagerClose: Boolean = false): Merge[T] = new Merge(inputPorts, eagerClose)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -31,11 +32,11 @@ object Merge {
|
|||
*
|
||||
* '''Backpressures when''' downstream backpressures
|
||||
*
|
||||
* '''Completes when''' all upstreams complete
|
||||
* '''Completes when''' all upstreams complete (eagerClose=false) or one upstream completes (eagerClose=true)
|
||||
*
|
||||
* '''Cancels when''' downstream cancels
|
||||
*/
|
||||
class Merge[T](val inputPorts: Int) extends GraphStage[UniformFanInShape[T, T]] {
|
||||
class Merge[T] private (val inputPorts: Int, val eagerClose: Boolean) extends GraphStage[UniformFanInShape[T, T]] {
|
||||
val in: immutable.IndexedSeq[Inlet[T]] = Vector.tabulate(inputPorts)(i ⇒ Inlet[T]("Merge.in" + i))
|
||||
val out: Outlet[T] = Outlet[T]("Merge.out")
|
||||
override val shape: UniformFanInShape[T, T] = UniformFanInShape(out, in: _*)
|
||||
|
|
@ -65,8 +66,6 @@ class Merge[T](val inputPorts: Int) extends GraphStage[UniformFanInShape[T, T]]
|
|||
else tryPull(in)
|
||||
}
|
||||
|
||||
private def tryPull(in: Inlet[T]): Unit = if (!isClosed(in)) pull(in)
|
||||
|
||||
in.foreach { i ⇒
|
||||
setHandler(i, new InHandler {
|
||||
override def onPush(): Unit = {
|
||||
|
|
@ -78,10 +77,15 @@ class Merge[T](val inputPorts: Int) extends GraphStage[UniformFanInShape[T, T]]
|
|||
} else enqueue(i)
|
||||
}
|
||||
|
||||
override def onUpstreamFinish() = {
|
||||
runningUpstreams -= 1
|
||||
if (upstreamsClosed && !pending) completeStage()
|
||||
}
|
||||
override def onUpstreamFinish() =
|
||||
if (eagerClose) {
|
||||
in.foreach(cancel)
|
||||
runningUpstreams = 0
|
||||
if (!pending) completeStage()
|
||||
} else {
|
||||
runningUpstreams -= 1
|
||||
if (upstreamsClosed && !pending) completeStage()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -113,8 +117,9 @@ object MergePreferred {
|
|||
* Create a new `MergePreferred` with the specified number of secondary input ports.
|
||||
*
|
||||
* @param secondaryPorts number of secondary input ports
|
||||
* @param eagerClose if true, the merge will complete as soon as one of its inputs completes.
|
||||
*/
|
||||
def apply[T](secondaryPorts: Int): MergePreferred[T] = new MergePreferred(secondaryPorts)
|
||||
def apply[T](secondaryPorts: Int, eagerClose: Boolean = false): MergePreferred[T] = new MergePreferred(secondaryPorts, eagerClose)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -134,7 +139,7 @@ object MergePreferred {
|
|||
*
|
||||
* A `Broadcast` has one `in` port and 2 or more `out` ports.
|
||||
*/
|
||||
class MergePreferred[T] private (secondaryPorts: Int) extends GraphStage[MergePreferred.MergePreferredShape[T]] {
|
||||
class MergePreferred[T] private (val secondaryPorts: Int, val eagerClose: Boolean) extends GraphStage[MergePreferred.MergePreferredShape[T]] {
|
||||
override val shape: MergePreferred.MergePreferredShape[T] =
|
||||
new MergePreferred.MergePreferredShape(secondaryPorts, "MergePreferred")
|
||||
|
||||
|
|
@ -169,8 +174,6 @@ class MergePreferred[T] private (secondaryPorts: Int) extends GraphStage[MergePr
|
|||
else tryPull(in)
|
||||
}
|
||||
|
||||
private def tryPull(in: Inlet[T]): Unit = if (!isClosed(in)) pull(in)
|
||||
|
||||
// FIXME: slow iteration, try to make in a vector and inject into shape instead
|
||||
(0 until secondaryPorts).map(in).foreach { i ⇒
|
||||
setHandler(i, new InHandler {
|
||||
|
|
@ -183,10 +186,16 @@ class MergePreferred[T] private (secondaryPorts: Int) extends GraphStage[MergePr
|
|||
} else enqueue(i)
|
||||
}
|
||||
|
||||
override def onUpstreamFinish() = {
|
||||
runningUpstreams -= 1
|
||||
if (upstreamsClosed && !pending && !priority) completeStage()
|
||||
}
|
||||
override def onUpstreamFinish() =
|
||||
if (eagerClose) {
|
||||
(0 until secondaryPorts).foreach(i ⇒ cancel(in(i)))
|
||||
cancel(preferred)
|
||||
runningUpstreams = 0
|
||||
if (!pending) completeStage()
|
||||
} else {
|
||||
runningUpstreams -= 1
|
||||
if (upstreamsClosed && !pending && !priority) completeStage()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -198,10 +207,15 @@ class MergePreferred[T] private (secondaryPorts: Int) extends GraphStage[MergePr
|
|||
}
|
||||
}
|
||||
|
||||
override def onUpstreamFinish() = {
|
||||
runningUpstreams -= 1
|
||||
if (upstreamsClosed && !pending && !priority) completeStage()
|
||||
}
|
||||
override def onUpstreamFinish() =
|
||||
if (eagerClose) {
|
||||
(0 until secondaryPorts).foreach(i ⇒ cancel(in(i)))
|
||||
runningUpstreams = 0
|
||||
if (!pending) completeStage()
|
||||
} else {
|
||||
runningUpstreams -= 1
|
||||
if (upstreamsClosed && !pending && !priority) completeStage()
|
||||
}
|
||||
})
|
||||
|
||||
setHandler(out, new OutHandler {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue