Skip to content

Commit

Permalink
尝试实现线性状态机
Browse files Browse the repository at this point in the history
Signed-off-by: YangDR <[email protected]>
  • Loading branch information
YdrMaster committed Aug 24, 2018
1 parent b2e59b2 commit 72a016e
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 30 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.mechdancer.dataflow.external.stateMachine.core

data class MachineSnapshot<T>(
val current: StateMember<T>,
val value: T
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.mechdancer.dataflow.external.stateMachine
package org.mechdancer.dataflow.external.stateMachine.core

import org.mechdancer.dataflow.core.*
import org.mechdancer.dataflow.core.internal.ReceiveCore
Expand All @@ -16,8 +16,8 @@ import java.util.concurrent.atomic.AtomicBoolean
* 广播方式收发状态转移记录
*/
class StateMachine<T>(override val name: String) :
IBridgeBlock<MachineState<T>>,
IReceivable<MachineState<T>> {
IBridgeBlock<MachineSnapshot<T>>,
IReceivable<MachineSnapshot<T>> {
override val uuid = UUID.randomUUID()!!
override val defaultSource by lazy { DefaultSource(this) }

Expand All @@ -27,11 +27,11 @@ class StateMachine<T>(override val name: String) :

private val runningFlag = AtomicBoolean(false)
val running get() = runningFlag.get()
val ending = State(this) { it }
val ending = StateMember(this) { it }

private val receiveCore = ReceiveCore()
private val sourceCore = SourceCore<MachineState<T>>(1)
private val targetCore = TargetCore<MachineState<T>> { s ->
private val sourceCore = SourceCore<MachineSnapshot<T>>(1)
private val targetCore = TargetCore<MachineSnapshot<T>> { s ->
runningFlag.set(!(s.current === ending))
sourceCore.offer(s).let { newId ->
Link[this]
Expand All @@ -41,7 +41,7 @@ class StateMachine<T>(override val name: String) :
receiveCore.call()
}

override fun offer(id: Long, link: Link<MachineState<T>>) = targetCore.offer(id, link)
override fun consume(id: Long): Message<out MachineState<T>> = sourceCore[id]
override fun offer(id: Long, link: Link<MachineSnapshot<T>>) = targetCore.offer(id, link)
override fun consume(id: Long): Message<out MachineSnapshot<T>> = sourceCore[id]
override fun receive() = receiveCore getFrom sourceCore
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.mechdancer.dataflow.external.stateMachine
package org.mechdancer.dataflow.external.stateMachine.core

import org.mechdancer.dataflow.core.*
import org.mechdancer.dataflow.core.internal.SourceCore
Expand All @@ -10,10 +10,10 @@ import java.util.*
* 状态
* 连接到状态机的状态节点
*/
class State<T>(
class StateMember<T>(
private val owner: StateMachine<T>,
loop: Boolean = false,
override val name: String = "State",
override val name: String = "StateMember",
private val action: (T) -> T)
: IBridgeBlock<T> {
override val uuid = UUID.randomUUID()!!
Expand All @@ -26,7 +26,7 @@ class State<T>(
ExecutableOptions(executor = owner.dispatcher)
) { event ->
val out = action(event)
owner post MachineState(this, out)
owner post MachineSnapshot(this, out)
sourceCore.offer(out).let { newId ->
Link[this]
.filter { it.options.predicate(out) }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.mechdancer.dataflow.external.stateMachine.machines

import org.mechdancer.dataflow.core.link
import org.mechdancer.dataflow.core.post
import org.mechdancer.dataflow.external.stateMachine.core.StateMachine
import org.mechdancer.dataflow.external.stateMachine.core.StateMember

class StateList<T> {
private val list = mutableListOf<Pair<Int, (T) -> T>>()

fun once(action: (T) -> T) {
list.add(1 to action)
}

fun loop(times: Int, action: (T) -> T) {
assert(times > 0)
list.add(times to action)
}

fun forever(action: (T) -> T) {
list.add(Int.MAX_VALUE to action)
}

private infix fun Pair<Int, (T) -> T>.buildIn(
machine: StateMachine<Pair<Int, T>>
) = StateMember(machine, first > 1) {
it.first + 1 to second(it.second)
}

fun build(): (T) -> Unit {
val machine = StateMachine<Pair<Int, T>>("linearStateMachine")
val stateList = mutableListOf(list[0] buildIn machine)
var stepCount = list[0].first
for (i in 1..list.lastIndex) {
stateList.add(list[i] buildIn machine)
val x = stepCount
link(stateList[i - 1], stateList[i]) { it.first >= x }
stepCount = (stepCount + list[i].first).takeIf { it > 0 } ?: Int.MAX_VALUE
}
return {
stateList.first() post (0 to it)
}
}
}

fun <T> linearStateMachine(block: StateList<T>.() -> Unit) =
StateList<T>().apply(block).build()
22 changes: 10 additions & 12 deletions src/test/kotlin/StateMachineTest.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import org.mechdancer.dataflow.core.link
import org.mechdancer.dataflow.core.post
import org.mechdancer.dataflow.external.stateMachine.State
import org.mechdancer.dataflow.external.stateMachine.StateMachine
import org.mechdancer.dataflow.external.stateMachine.machines.linearStateMachine

fun main(args: Array<String>) {
val machine = StateMachine<Int>("for")
val add = State(machine) { x -> x + 1 }
val print = State(machine) { x -> x.also { println(it) } }
link(add, print) { it < 1000 }
link(add, machine.ending) { it >= 1000 }
link(print, add)
print post 0
while (!machine.running);
val startWith = linearStateMachine<Int> {
once { println(it); it + 1 }
loop(3) { println(it); it * 2 }
once { println(it); it }
forever { it }
}

startWith(3)
while (true);
}

0 comments on commit 72a016e

Please sign in to comment.