예제 #1
0
파일: cfsm.go 프로젝트: nickng/dingo-hunter
func (sys *CFSMs) chanToMachine(ch Role, T string, m *cfsm.CFSM) {
	q0 := m.NewState()
	qEnd := m.NewState()
	for _, machine := range sys.Roles {
		q1 := m.NewState()
		// q0 -- Recv --> q1
		tr0 := cfsm.NewRecv(machine, T)
		tr0.SetNext(q1)
		q0.AddTransition(tr0)
		// q1 -- Send --> q0
		for _, machine2 := range sys.Roles {
			if machine.ID != machine2.ID {
				tr1 := cfsm.NewSend(machine2, T)
				tr1.SetNext(q0)
				q1.AddTransition(tr1)
			}
		}
		// q0 -- STOP --> qEnd (same qEnd)
		tr2 := cfsm.NewRecv(machine, STOP)
		tr2.SetNext(qEnd)
		qEnd.AddTransition(tr2)
		// qEnd -- STOP --> qEnd
		for _, machine2 := range sys.Roles {
			if machine.ID != machine2.ID {
				tr3 := cfsm.NewSend(machine2, STOP)
				tr3.SetNext(qEnd)
				qEnd.AddTransition(tr3)
			}
		}
	}
	m.Start = q0
}
예제 #2
0
파일: cfsm.go 프로젝트: nickng/dingo-hunter
func (sys *CFSMs) nodeToMachine(role Role, node Node, q0 *cfsm.State, m *cfsm.CFSM) {
	switch node := node.(type) {
	case *SendNode:
		to, ok := sys.Chans[node.To()]
		if !ok {
			log.Fatal("Cannot Send to unknown channel", node.To().Name())
		}
		tr := cfsm.NewSend(to, node.To().Type().String())
		qSent := m.NewState()
		for _, c := range node.Children() {
			sys.nodeToMachine(role, c, qSent, m)
		}
		tr.SetNext(qSent)
		q0.AddTransition(tr)

	case *RecvNode:
		from, ok := sys.Chans[node.From()]
		if !ok {
			log.Fatal("Cannot Recv from unknown channel", node.From().Name())
		}
		msg := node.From().Type().String()
		if node.Stop() {
			msg = STOP
		}
		tr := cfsm.NewRecv(from, msg)
		qRcvd := m.NewState()
		for _, c := range node.Children() {
			sys.nodeToMachine(role, c, qRcvd, m)
		}
		tr.SetNext(qRcvd)
		q0.AddTransition(tr)

	case *EndNode:
		ch, ok := sys.Chans[node.Chan()]
		if !ok {
			log.Fatal("Cannot Close unknown channel", node.Chan().Name())
		}
		tr := cfsm.NewSend(ch, STOP)
		qEnd := m.NewState()
		for _, c := range node.Children() {
			sys.nodeToMachine(role, c, qEnd, m)
		}
		tr.SetNext(qEnd)
		q0.AddTransition(tr)

	case *NewChanNode, *EmptyBodyNode: // Skip
		for _, c := range node.Children() {
			sys.nodeToMachine(role, c, q0, m)
		}

	case *LabelNode:
		sys.States[m][node.Name()] = q0
		for _, c := range node.Children() {
			sys.nodeToMachine(role, c, q0, m)
		}

	case *GotoNode:
		qTarget := sys.States[m][node.Name()]
		for _, c := range node.Children() {
			sys.nodeToMachine(role, c, qTarget, m)
		}

	default:
		log.Fatalf("Unhandled node type %T", node)
	}
}