The GENFSM of Erlang implemented with go.

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

For Erlang's finite state machine, refer to Erlang's four behaviour two-GEN_FSM this article.

Finite state machines can be expressed by the following formula

State (s) x Event (E), and Actions (A), state (S ')

These two days is just idle, with Golang realized a bit, say not much, directly on the code

Package Utilimport ("errors" "Reflect" "Sync" "Time" "Unicode" "Unicode/utf8" "Util/log") var typeoferror = reflect. TypeOf ((*error) (nil)). Elem () type FSM struct {sync. Mutexstopreason STRINGRCVR reflect. Value//Receiver of methods for the Servicetyp reflect. Type//Type of the Receivermethod map[string]reflect. Methodevent Chan Eventquit Chan intstate stringstopped bool}type event struct {event Stringparam in Terface{}timeout Int}func (FSM *FSM) IsStopped () bool {FSM. Lock () defer FSM. Unlock () return Fsm.stopped}func (FSM *FSM) sendevent (event string, param interface{}) {FSM. Lock () defer FSM. Unlock () If fsm.stopped {return}fsm.event <-event{event, param, 0}}func (FSM *FSM) Init (start string) Error {If _, OK: = Fsm.method[start];!ok {return errors. New ("Not Found-state")}fsm.state = Startgo func () {for {select {case e: = <-fsm.event:go FSM. Callstate (e) Case <-fsm.quit:goto Close}}close:close (fsm.event) Close (Fsm.quit)} () return Nil}func (FSM *FSM) callstAte (e Event) {FSM. Lock () defer FSM. Unlock () If function, OK: = Fsm.method[fsm.state]; OK {returnvalues: = function. Func.call ([]reflect. VALUE{FSM.RCVR, reflect. ValueOf (e.event), reflect. ValueOf (E.param), reflect. ValueOf (E.timeout)}) Nextstate: = Returnvalues[0]. String () Timeout: = Returnvalues[1]. Int () Errinter: = Returnvalues[2]. Interface () ErrMsg: = "" if errinter! = Nil {errmsg = Errinter. ( Error). Error ()}if nextstate = = "Stop" {FSM. Stop (errmsg) fsm.quit <-1return}if errmsg! = "" {log. LogError (errmsg)}fsm.state = Nextstateif Timeout > 0 {go FSM. Delaycall (time. Duration (timeout))}}}func (FSM *FSM) Delaycall (timeout time. Duration) {select {case <-time. After (timeout * time. Millisecond): fsm.event <-event{"Timeout", 0, int (timeout)}}}func (FSM *FSM) Stop (message string) {FSM. Stopreason = messagefsm.stopped = True}func (FSM *FSM) Close () {FSM. Lock () defer FSM. Unlock () If fsm.stopped {return}fsm.quit <-1}func NEWFSM (FSM interface{}) *FSM {f: = &fsm{typ:reflect. TypeOf (FSM), RCVR:Reflect. ValueOf (FSM), Event:make (Chan event), Quit:make (chan int)}f.method = Suitablemethods (F.typ, True) return F}func Isexport Ed (name string) bool {Rune, _: = UTF8. Decoderuneinstring (name) return Unicode. Isupper (rune)}func suitablemethods (Typ reflect. Type, reporterr bool) map[string]reflect. Method {methods: = Make (Map[string]reflect. Method) for M: = 0; M < Typ. Nummethod (); m++ {method: = Typ. Method (m) Mtype: = method. Typemname: = method. Nameif!isexported (mname) {continue}//Method needs four ins:receiver, string, interface{}, Int.if mtype. Numin ()! = 4 {if Reporterr {log. LogError ("Method", Mname, "has wrong number of ins:", Mtype. Numin ())}continue}//first Arg must be a string.if mtype. In (1). Kind ()! = reflect. String {if Reporterr {log. LogError ("Method", Mname, "arg1 type not a string:", Mtype. In (1). Kind ())}continue}//Second Arg must be a interface.if mtype. In (2). Kind ()! = reflect. Interface {if Reporterr {log. LogError ("Method", Mname, "arg2 type not a interface:", Mtype. In (2). Kind ())}continue}//Third Arg must be a int.if mtype. In (3). Kind ()! = reflect. Int {if Reporterr {log. LogError ("Method", Mname, "arg3 type not a int:", mtype. In (3). Kind ())}continue}//Method needs three out.if mtype. Numout ()! = 3 {if Reporterr {log. LogError ("Method", Mname, "has wrong number of outs:", Mtype. Numout ())}continue}if mtype. Out (0). Kind ()! = reflect. String {if Reporterr {log. LogError ("Method", Mname, "out1 type not a string:", Mtype. Out (0). Kind ())}continue}if mtype. Out (1). Kind ()! = reflect. Int {if Reporterr {log. LogError ("Method", Mname, "out1 type not a int:", mtype. Out (1). Kind ())}continue}if mtype. Out (2)! = Typeoferror {if Reporterr {log. LogError ("Method", Mname, "out3 type not a" error: ", Mtype. In (2). Kind ())}continue}methods[mname] = Method}return Methods}

Here's how to use it:

Type GOFSM struct {}func (f *GOFSM) State1 (event string, param interface{}, T int) (Nextstate string, timeout int, err err OR) {log. LogMessage (event, Param.) ( int)) return "State2", +, nil//If timeout is greater than 0, the next state is automatically called after timeout milliseconds, and the next state event is Timeout}func (f *GOFSM) State2 (event String, param interface{}, T int) (Nextstate string, timeout int, err error) {log. LogMessage (event) return "Stop", 0, errors. New ("Stop OK")//nextstate=stop stops the state machine, and err is the stop Reason}func main () {f: = util. NEWFSM (&gofsm{}) f.init ("State1")     //initial state F. Sendevent ("Do", 1)//Send event time. Sleep (time. Second * 1)}

All state callback functions must start with a capital letter and the prototype must be

The event is the name of the events, Param is the argument for the event, and T>0 indicates that this is a delay event. Return value: Nextstate is the new state, must have the same name as the state callback function, and if "stop" means there is no subsequent state, the state machine stops. Timeout>0 represents a delay callback, which generates a timeout event after the timeout time.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.