Results 1 to 20 of 27

Thread: How to design a state machine in face of non-blocking I/O?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: How to design a state machine in face of non-blocking I/O?

    Not the best pictures but I hope they are clear. The first one represents the "request" part of the system. The output part of each transition is a new state for the second submachine (second image) that marks the "job" state. {LOADED} is a trigger (your network event) and <CONNECT> is a user event.

    Bear in mind that there are few transitions missing - when each of the calls fails you should do error recovery and change the state of both machines properly.

    Note that this design doesn't assume that you need to login to the site to be able to perform queries (and you can even perform a few queries, then login and then perform some more queries) - which proves you don't need any special "Connect with intent to login" states - it's the input that decides which transition will be triggered and you don't need to know it upfront.
    Attached Images Attached Images
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  2. #2
    Join Date
    May 2009
    Posts
    133
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    10
    Thanked 4 Times in 3 Posts

    Default Re: How to design a state machine in face of non-blocking I/O?

    Thank you very much for the time you spent on these pictures.

    I'd like to ask a couple of questions because it seems to me like pictures are not consistent.

    Let's take Idle and Connecting states from Rysunek1.
    1. Transition from Idle to Connecting is marked with IDLE, <CONNECT>/- what I take as "When <CONNECT> user event is received go to Connecting state. Don't know what "/-" part means, however.
    2. The opposite transition is marked as {LOADED}/CONNECTED which I don't get. I understand the first part of this transition's description - {LOADED} - but have no idea what CONNECTED here is supposed to mean.
    Shouldn't the format of each transition's description be exactly the same? In the above case the first description is in format state, event/- and the second description is in format event/?

    Quote Originally Posted by wysota View Post
    Note that this design doesn't assume that you need to login to the site to be able to perform queries
    Why it doesn't assume this? It's fundamental constrain.

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by piotr.dobrogost View Post
    1. Transition from Idle to Connecting is marked with IDLE, <CONNECT>/- what I take as "When <CONNECT> user event is received go to Connecting state. Don't know what "/-" part means, however.
    When the other subsystem is in "IDLE" state and CONNECT is received as input to the system, go to Connecting state and output nothing.

    2. The opposite transition is marked as {LOADED}/CONNECTED which I don't get. I understand the first part of this transition's description - {LOADED} - but have no idea what CONNECTED here is supposed to mean.
    When you receive the network event, move into the idle state and output CONNECTED (which will move the other subsystem to the CONNECTED state).

    Shouldn't the format of each transition's description be exactly the same? In the above case the first description is in format state, event/- and the second description is in format event/?
    It is the same: "<state of other machine>, <external input> / <output>"


    Why it doesn't assume this? It's fundamental constrain.
    No, it's not. You might want to perform queries as an unlogged user. But anyway, it doesn't assume you have to do it but it doesn't mean you have to take that path - you can remove the dead transitions if you want.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. #4
    Join Date
    May 2009
    Posts
    133
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    10
    Thanked 4 Times in 3 Posts

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by wysota View Post
    When the other subsystem is in "IDLE" state and CONNECT is received (...)
    This means you have to check the state of the other (let's call it network) subsystem from outside of it. I was looking for some method allowing to find out which state a QStateMachine is in but don't see any such... When you think of it it's logical there is no such a method as a state machine itself is a tool that should be used to handle logic internally. This reminds me of Untangling the Signal Slot Spaghetti with SCXML where the author states that the very important purpose of state machines is to remove handling program flow manually with if and switch statements. As you know instead of having one Idle state in the first subsystem (let's call it user subsystem) and checking what the state of the other one is we could just introduce new states like Idle-Connected and Idle-LoggedIn and this way we wouldn't need to check manually for the state of network subsystem from within user subsystem. This represents going from if type of managing program's logic to state machine type of managing program's logic. Dividing my current state machine into two new ones and checking (using if) what's the state of the other one is like going in opposite direction. Any thoughts?

    Quote Originally Posted by wysota View Post
    When you receive the network event, move into the idle state and output CONNECTED (which will move the other subsystem to the CONNECTED state).
    I thought the idea was to direct network events from withing LoadFinished handler directly to this other subsystem which is responsible for network state. Would it be viable? Would it be better? Wouldn't then be an issue of synchronization between the two subsystems?

    Quote Originally Posted by wysota View Post
    It is the same: "<state of other machine>, <external input> / <output>"
    Ok.

    Quote Originally Posted by wysota View Post
    you can remove the dead transitions if you want.
    Ok.
    Last edited by piotr.dobrogost; 14th August 2009 at 09:09.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by piotr.dobrogost View Post
    This means you have to check the state of the other (let's call it network) subsystem from outside of it.
    Yes, of course.

    I was looking for some method allowing to find out which state a QStateMachine is in but don't see any such...
    How about using onEntry() and onExit()?

    When you think of it it's logical there is no such a method as a state machine itself is a tool that should be used to handle logic internally. This reminds me of Untangling the Signal Slot Spaghetti with SCXML where the author states that the very important purpose of state machines is to remove handling program flow manually with if and switch statements.[/quote]
    That's true but nobody says you have to do that. Transitions are fired upon some external input - all you need to do is to make one machine provide input to the other.

    I thought the idea was to direct network events from withing LoadFinished handler directly to this other subsystem which is responsible for network state. Would it be viable? Would it be better? Wouldn't then be an issue of synchronization between the two subsystems?
    Try and see for yourself, I'm not an oracle
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    May 2009
    Posts
    133
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    10
    Thanked 4 Times in 3 Posts

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by wysota View Post
    How about using onEntry() and onExit()?
    You mean to make the machine itself store its state outside and read it from there?
    That wouldn't be atomic operation then. Don't know if that would be a problem but... Let's forget for a moment about my case. Each QStateMachine has its own event loop so it works fully asynchronously. Having non-atomic read of machine's state doesn't sound like a safe approach in this situation. What do you think?

    Quote Originally Posted by wysota View Post
    That's true but nobody says you have to do that. Transitions are fired upon some external input - all you need to do is to make one machine provide input to the other.
    So how would you code, without using conditional statements, let's say the transition Idle -- LOGGEDIN/<QUERY>/- --> Querying from your Rysunek1? To me it looks like you have to make _decision_ (so use conditional statement) in your code based on the information weather the network state machine is in LoggedIn state or it's not...

    Quote Originally Posted by wysota View Post
    Try and see for yourself, I'm not an oracle
    I thought programming is not about trying but about thinking, knowing and being sure something is right

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default

    Quote Originally Posted by piotr.dobrogost View Post
    You mean to make the machine itself store its state outside and read it from there?
    Something like that.

    That wouldn't be atomic operation then.
    Why not? It would be atomic from the state machine's point of view. The number of event loops doesn't matter. The thread count matters (if at all).

    So how would you code, without using conditional statements, let's say the transition Idle -- LOGGEDIN/<QUERY>/- --> Querying from your Rysunek1? To me it looks like you have to make _decision_ (so use conditional statement) in your code based on the information weather the network state machine is in LoggedIn state or it's not...
    I don't understand the problem Maybe you should try to write some code and then we could work on it?

    Quote Originally Posted by piotr.dobrogost View Post
    I thought programming is not about trying but about thinking, knowing and being sure something is right
    Then you were simply wrong
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    May 2009
    Posts
    133
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    10
    Thanked 4 Times in 3 Posts

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by wysota View Post
    Something like that.
    Ok. What do you think about the fact there is no function to obtain current state in QStateMachine's API although the state in which a state machine is, well it's the most important part of its state as an object?

    Quote Originally Posted by wysota View Post
    I don't understand the problem Maybe you should try to write some code and then we could work on it?
    Qt Code:
    1. NetworkMachine * netMachine;
    2.  
    3. class UserMachine
    4. {
    5. public:
    6. class UserTransition : public QAbstractTransition
    7. {
    8. //...
    9. }
    10. //...
    11. }
    12.  
    13.  
    14. bool UserMachine::UserTransition::eventTest(QEvent * event )
    15. {
    16. if (event.type() == UserMachine::EventType::Query)
    17. {
    18. // we are forced to use switch here...
    19. switch (currentState(netMachine))
    20. {
    21. case NetworkMachine::Connected:
    22. case NetworkMachine::LoggedIn:
    23. case NetworkMachine::Result:
    24. return true;
    25. default:
    26. return false;
    27. }
    28. }
    29.  
    30. }
    To copy to clipboard, switch view to plain text mode 

    We need this switch statement above because we have to decide if we're doing transition or not based on the state of the network machine.
    If we had more states in the user machine we wouldn't have to check the state of network machine. We would had enough number of states we wouldn't have need the network machine at all... What do you think?
    Last edited by piotr.dobrogost; 14th August 2009 at 18:27.

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by piotr.dobrogost View Post
    Ok. What do you think about the fact there is no function to obtain current state in QStateMachine's API although the state in which a state machine is, well it's the most important part of its state as an object?
    There are the entered() and exited() signals in QState. That should be enough for everything.

    The code doesn't do anything yet, so I'm not going to comment on that.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    May 2009
    Posts
    133
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    10
    Thanked 4 Times in 3 Posts

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by wysota View Post
    The code doesn't do anything yet, so I'm not going to comment on that.
    What do you mean? It shows that when user machine gets <query> event it has to check the state of network machine and based on this information make a decision weather to trigger transition or not.

    bool QAbstractTransition::eventTest ( QEvent * event ) [pure virtual protected]
    This function is called to determine whether the given event should cause this transition to trigger. Reimplement this function and return true if the event should trigger the transition, otherwise return false.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,376
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: How to design a state machine in face of non-blocking I/O?

    Quote Originally Posted by piotr.dobrogost View Post
    What do you mean? It shows that when user machine gets <query> event it has to check the state of network machine and based on this information make a decision weather to trigger transition or not.
    Get something that compiles and runs.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #12
    Join Date
    May 2009
    Posts
    133
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    10
    Thanked 4 Times in 3 Posts

    Default Re: How to design a state machine in face of non-blocking I/O?

    I created sketches of current design and the one you're proposing to be able to visually compare one with the other. In addition to .png files I'm attaching zipped source of these sketches in .dia format in case someone would like to use/modify them easily in open source Dia application.

    al.current.png - the design of the state machine I'm using currently

    al.new.user.png - the one of the two state machines you are proposing, controlling user actions

    al.new.network.png - the one of the two state machines you are proposing, controlling network state

    I haven't put any transitions nor events in the sketches of the design you are proposing because I don't understand notation you used in your sketches. See my previous post.
    Attached Images Attached Images
    Attached Files Attached Files
    Last edited by piotr.dobrogost; 13th August 2009 at 21:36.

Similar Threads

  1. Qt State Machine Examples don't compile
    By vitalyx in forum Newbie
    Replies: 0
    Last Post: 4th April 2009, 14:19

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.