LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

producer consumer vs state machine

Hi there,

I have been on and around for quite a while to understand how can I re-design an application, which was originally built using a mix of sequence structure, while loops and event structures. And now I am making a newer version of the same application, for research purposes, while learning the LabVIEW techniques. Earlier I used LabVIEW versions 5 and 6 to make simple programs for fuzzy logic and neural networks. And that's not a good reference.

 

Ok, after learning that Producer Consumer (PC) and Standard State Machines (SSM or SM) are two new approaches for a better (scalable, flexible and efficient) coding as suggest by veterans, in one thread where I asked about another issue, I have started digging into this topic and now I am on a point where I have to implement it finally (spent pretty much time in the learning phase).

 

I have several questions.

 

To start the discussion, I would give a brief description of my application.

 

  • It's a networked application, where the network communication happens using DataSocket (one reason to use LabVIEW as the environment).
  • We are talking about the client application, which communicates with other applications on remote computer, via Internet.
  • User interface involves a tab control, with several pages-

 

  1. On startup, the controls/indicators (now onwards referred as controls only), are initialized, datasocket connection is checked (rather internet is checked, and a connection established with the remote datasocket server) (page 1)
  2. If connected to the datasocket server, the user selects Login/Registration (page 2)
  3. Login and/or Registration happen on page 3/4
  4. Then the user sees a table of remote users to connect to (page 5)
  5. Upon selection of a remote user, and after clicking on "connect", the user will see a video indicator, with a lot of other controls. (page 6)
  6. On this page with video indicator and controls, the user has a lot of activities, in which many messages are sent and received to/from the remote machine.
  7. the user may disconnect and go back to page 5, and log out and go back to page 2 and so on.

 

I hope this is clear.

 

 

I have thought about two different ways to do this application. Using PS or by SSM.

 

In the attachments, I have given a diagram (with errors, of course, because of unlinked controls), for each of the approach, plus the original application's diagram.

 

I hope this is sufficient for anybody to understand my case and give suggestions.

 

 

I am looking for suggestions about which is a better model for my type of case. I have been to discussions like this one and saw that there are many issues regarding dequeue in PC model. So I am curious to know if SSM is a better and latest model or it's more primitive? Which looks better for my application's performance?

 

Thanks ahead!

Vaibhav
Download All
Message 1 of 33
(8,484 Views)

I think for your case the SSM would be the best

 

normally your don't use a case statment to start a while loop

Harold Timmis
htimmis@fit.edu
Orlando,Fl
*Kudos always welcome:)
Message 2 of 33
(8,463 Views)

Yes, based on your description, a state machine sounds like the appropriate architecture.  But don't think that producer/consumer and state machine are mutually exclusive.  Let the state machine control the order of you code, your sequencing of actions, and when you may have to branch to other actions.  You can use several producer consumer loops in parallel if needed.  Such as a separate loop that is passed data for logging to a file.  Or a loop that handles the data acquisition functions.

 

Be careful about the way you laid out your example in SSMDesign.vi.  It is generally a bad idea to have multiple event structures, and how you have them separated into different cases of your case structure.  Even if an event structure is not in the line of execution, it will still capture events for processing.  For example, let's say your state machine is going through the page 2 state, and may not be for a while.  But the user happens to the login button.  (How can they do that?  Well the tab control is a control, and you haven't prevented them from changing to other tabs.  Perhaps they changed to tabe 2 and just clicked the login button.)  That Login Value change event gets queued up in that event structure.  When the code finally gets around to the Page 2 state, the Login Value Change will immediately fire and that may be a surprising action to the user because it could have been a long time since they had actually pressed that button.

 

When using Event structures, there is generally one that handles all the events.  It is often a producer in a producer/consumer architecture passing the data from the event to the consumer loop, which might be a state machine.  Perhaps if the event is meaningless because of the current state, the state machine just ignores it.  If it is meaningful, then perhaps the next state depends on the event data that gets passed.

 

You could also build the event structure into the state machine.  Place a small timeout on the event structure and build the statemachine cases into the timeout case of the event structure.  That way if an event happens (like an stop button being pressed, the event structure immediately fires and decides to change the state to the "Exit" case.  If no events happen, then after the small timeout has passed, then the shift register feeds into the timeout case and the appropriate case of the case structure executes (such as the Exit case).

Message 3 of 33
(8,448 Views)

@ Harold

Thanks. Any suggestion how can I start and stop that loop in parallel with other loops? Like, if some event occurs, the loop should start execution, and keep on moving, while other events are being traced and executed.

 

@ Ravens

 

Thanks for the detailed comment.

One thing I would clarify. The user will not be able to switch between the pages using the tab control. The program will direct appropriate page to the user. I kept the tabs visible just for your idea of the pages. Sorry, I didn't mention that.

 

Do you think it's still a bad design?

 

Yes, I agree about only one event structure to handle all the events. But since the user will not be able to click somewhere else, other than those possible controls, I thought to keep it like this.

I thought the events are captured only if we are in that case. I think I am wrong, right? Ok, The events will be captured, but will not be executed until in that case.

And that's the reason why I have two separate event structures, in two separate phases of the program.

Because, prior to page 6, the events will occur sequencially. The user will click somewhere, then some message will be transmitted over DataSocket, then some message may come , then again some user action and so on. But, when the user starts using page 6, there will be parallel process of user controls events and actions, and incoming messages and corresponding actions. For this, in the page 6, I need a different kind of execution. So I separated the two event structures.

 

At first I thought to have SSM, and then I thought to PC, just because I can have two separate parallel processes - one for user events, and another for messages (because that way I can take maximum advantage of message tracking). But looking at other complexities, I find SSM more appropriate. Can you please tell me how can I have my message loop and events loop parallel to each other and just one event structure?

 

 

Vaibhav
0 Kudos
Message 4 of 33
(8,441 Views)

Vaibhav wrote:

@ Harold

Thanks. Any suggestion how can I start and stop that loop in parallel with other loops? Like, if some event occurs, the loop should start execution, and keep on moving, while other events are being traced and executed.

 

In those examples where you had a while loop inside a case structure, that bit of code will only execute one time.  It will immediately read the boolean at the start of the program, if the value was true before the porgram started, then the while loop will run.  Once that while loop stops, the case structure will end.  It will never execute again unless you completely stop and restart your program.  If the boolean is false before the program starts, the false case will execute immediately.  Nothing happens since it is empty and it is done, never to run again (unless you stop and restart your VI)  You should turn the structure around.  Put the case structure in the while loop.  Make sure you put a small wait statement in the loop so that it doesn't run full speed eating up CPU cycles just polling the status of the boolean.

 

@ Ravens

 

Thanks for the detailed comment.

One thing I would clarify. The user will not be able to switch between the pages using the tab control. The program will direct appropriate page to the user. I kept the tabs visible just for your idea of the pages. Sorry, I didn't mention that.

 

Do you think it's still a bad design?

If the tabs will be hidden or disabled, you will probably be okay.  I wouldn't call it a bad design.  I wouldn't do it that way.  But as long as you understand the possibility of problems and prevent that.  Especially some time down the road when you modify the program in some other way that could lead to a problem because you forgot about the dependencies of the event structures on the state of the state machine. 

 

 

Yes, I agree about only one event structure to handle all the events. But since the user will not be able to click somewhere else, other than those possible controls, I thought to keep it like this.

I thought the events are captured only if we are in that case. I think I am wrong, right? Events are captured at any time, even if the case has never executed before, or will never execute.  Ok, The events will be captured, but will not be executed until in that case.

And that's the reason why I have two separate event structures, in two separate phases of the program.

Because, prior to page 6, the events will occur sequencially. The user will click somewhere, then some message will be transmitted over DataSocket, then some message may come , then again some user action and so on. But, when the user starts using page 6, there will be parallel process of user controls events and actions, and incoming messages and corresponding actions. For this, in the page 6, I need a different kind of execution. So I separated the two event structures.

 

At first I thought to have SSM, and then I thought to PC, just because I can have two separate parallel processes - one for user events, and another for messages (because that way I can take maximum advantage of message tracking). But looking at other complexities, I find SSM more appropriate. Can you please tell me how can I have my message loop and events loop parallel to each other and just one event structure?

 

 


You can have a dequeue function in your state machine loop and have it be a consumer loop.  Use a timeout on the Dequeue.  If there is a timeout, have the statemachine execute normally after that perhaps just passing the enum wire straight into the case structure of the state machine.  If it doesn't timeout meaning you got a message, then look at the message that is dequeued and act on it.  Perhaps it means ignoring the enum coming in from the shift register and changing the enum to something else to feed into the case structure of the state machine.  Attached is an example

Message 5 of 33
(8,434 Views)

Thanks Ravens,

 

understood about the while loop inside the case structure. So have changed that into an independent loop. And that loop will be controlled by other variables/parameters ("MainEvents" case). I cannot put some kind of time delay on that loop since the video should be without interruption. in my previous applications it's working fine that way. so this way I'll keep here also. I needed to understand how labview functions.

 

Ys, I understand the risks of loose programming. I had missed to set the tab well. Now it's an indicator, so the user will not have chance to move. But also, to have a good programming practice, now the events are also in one place  (actually 2 places, but still better), more organized.  

Ok, in the attached version, I have removed the cases with 1 or 2 events, and merged them all in just one case - all the events prior to the page 6 will happen in that one case - "ConnectionEvents" and the page 6 executions wil be on MainEvents.

 

Ok, so events are captured at any time, but the program has to be in such a condition that these event will get executed, right? So for that it has to be in the case where it's expected tobe captured, so that it could be executed. It won't execute a case which is not selected right now, yes?

 

thanks for the example. I understand you're talking about handling either the message or the normal program execution, in just one loop/case structure. Right?

But this will mean that either the message will be processed or the other program part will be executed, but not both in parallel. And I am trying to do them in parallel, so that some action of some message will not hold some click event.

 

In the case that you sent me, if you're talking about handling messages and state machine in single case structure, I think it doesn't make sense to merge message events and normal program states to be handled in just one case diagram, since both have different sources of cases (different enumerators). So it will be a type clash. or you meant to handle all the states (of StatesEnum) in this case structure (of the consumer 2 loop example)?

But it's surely a good idea to execute in flow, but I think not in parallel. What do you say?

 

Also, in the new version, in the "MainEvents" case, the event structure is without any while loop. I think it should be in some while loop right?

Vaibhav
Download All
0 Kudos
Message 6 of 33
(8,424 Views)

Ravens Fan wrote:

 

You can have a dequeue function in your state machine loop and have it be a consumer loop... 

...Perhaps it means ignoring the enum coming in from the shift register and changing the enum to something else to feed into the case structure of the state machine.  Attached is an example


 

Ok, I think I got what you mean. You mean, to put the whole Case structure of the State machine ( to handle different states and change states) inside that case structure, and when there is no message, i.e.. timed out, go to a state where the GUI events are checked, right?

But then this is not parallel. I have to select between message procesing and event handling. If I understood correctly.

 

Vaibhav
0 Kudos
Message 7 of 33
(8,418 Views)

Vaibhav,

 

since the VI seems to be solely controller by user interaction, i'd rather suggest the User Interface Event Handler as code design. You can find this design pattern in the VI template browser.

This code design does not support multithreading in a useful way. So if you need something to happen in parallel, this code design does not work out very good for you.

 

The main issue with this "architectures": Once you decided to use one, you most often have to stick/live with it if if you find out later on, that this architecture does not support the features that you need....

 

LabVIEW has many possible approaches to solve the given task (as all programming languages do). So deciding "the best" (for this certain task) needs lots of experience which each developer has to collect on his/her own. So i suggest you (if you have the time for this) to create small "usability examples" for the application.

 

From what i have seen from your posted vis, i think a single loop architecture will be sufficient, but keep an eye on possible future changes!

 

hope this helps,

Norbert 

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 8 of 33
(8,351 Views)

To keep things simple and scalable for future expansion, I like to have single point sources for my data and user interaction, and single sinks for data handling.  In your case, this would mean one loop for events and one for datasocket monitoring.  Data handling should be done with a third loop.  If UI events need special handling, they can be a fourth loop or handled in a case structure in the main UI loop (asynchronous or synchronous - your choice).  This is a common architecture that is easily expandable (for a full blown example, see this post).  One key to making it work is separating action handling from events.  This allows you to essentially intermingle a state machine into a producer consumer architecture.

 

Short answer, you want both a state machine and a producer consumer architecture.  See the example above (all the posts) for an example.  It does essentially what you want to do, but using input from a sound card instead of datasockets.

Message 9 of 33
(8,336 Views)

Norbert,

 

Thanks for coming to discussion. Well, my VI is not only controlled by user events (the GUI, is controlled by user clicks, but the internal stuff is not). There has to be a constant tracking of incoming datasocket messages and depending on the code in those messages, a proper action needs to be taken.

 

From the others also, I have this suggestion of that single loop, and before beginning I had also planned to use that architecture, but I want to do parallel process of the message reading also. that's why need to do something more efficient in that single loop architecture. Though, I can just fit the whole "current" architecture into that single loop, which has 3-4 parallel while loops inside one particular "state" but I thought to make something more efficient, so asking here.  So instead of those 3-4 parallel loops, I thought to have something more systematic in my approach.

 

If you see the SSMDesign.vi , how would you accomodate the tracking of incoming messages while tracking user events and performing tasks, in parallel?

 

Thanks.

Vaibhav
0 Kudos
Message 10 of 33
(8,304 Views)