Jump to content

Are queues enough?


Recommended Posts

Hello everyone, I am building and testing a new (for me) architecture with LV6.1.

I made some tests to see if my idea is ready to work but even when the test system worked fine, my more "advanced" (=not so simple) version did not. I'm having a difficult time with probably race condition and perhaps something else as well.

I try to outline the system somewhat. There are four threads

  • User interface -send & receive
  • Com port polling -send
  • Test sequencer -send & receive
  • System supervisor -receive (only preview)

The user interface is the main communication controller, event handler, sending and receiving messages etc.

Second thread is polling communication ports and sending all the information to queue, this information is addressed always to user interface.

Test sequencer is time sensitive and it needs to be able to communicate in both directions, ask something from UI and then receive the answer. Sometimes however I do have the luxury to let this thread wait for the answer if I'm sure it is available and won't take long. Long = >100ms.

System supervisor would help in debugging and error situations, sort of look over the system and log different things. It's not ready yet. :thumbdown:

I use one queue for all communication between different threads.

One command is a cluster of

  • receiver's name
  • sender's name
  • timestamp
  • target
  • command
  • string of parameters

Senders do not wait for receipts unless the command is ask_value.

At first I sent only text through queue but then I changed text to cluster which I now think might contribute to my problems. At some point I receive Error #1 from all my attempts to read the queue even when the read timeout is set to -1. The error message from this doesn't help me much as I don't understand what the problem is but first remedy I'll try is flatten the command cluster to string and send that.

As I have more than one receivers I try to address the race condition by letting all receivers (2-3) read (and remove) uncontrolled the first command, check if it is for them and if not, put it back to first place, wait a small random time and try again. If I could somehow lock the queue until the receiver has decided what to do with the command, I could sleep a bit better but for now I think :unsure: I can do without locking and accept the fact that two readers might swap the first command a couple of times before they receive the one addressed to them.

So there. Do I need to lock the queue while I'm reading it? What problems lie ahead if I have to expand my system? Most of all, what improvements would you suggest :question:

Link to comment

Did some reading and found the probable cure for race condition between different readers. Without true understanding I tried to set the receiver to reentrant vi. I should have kept it just the opposite to let the receivers remain in their queue while waiting for commands to receive from the data queue.

Link to comment

I may have missed the point of what you're trying to achieve here, but in my experience you're trying to place to much in the UI.

Test sequencer is time sensitive and it needs to be able to communicate in both directions, ask something from UI and then receive the answer.

The UI should be left for just that, the user. It should not be asked for values so it should solely waiting for user input (in an ideal world ;-)).

However rather than go into more complicated structures, I suggest you check out the preview Q element node. That way you do not need to remove the element and re-queue it. If the element is not for you leave it alone, when one does arrive addressed to you remove it and add any response (if necessary) to the end of the queue.

In the long run, research on OOP techniques in LabVIEW, this is a much better design philosophy for transferring data across loops (without race conditions), IMHO. As it happens I use OOP coupled with the architecture you are creating (queue driven state machine) to great effect in just about every application I write.

OOP or GOOP as it's called in LabVIEW will also solve your problem of multiple readers requiring the same data, simply read the object data in each loop.

Link to comment

I think you caught my point very well and thank you for your answer.

As I told in my first post, I needed some data for test sequencer and this data needs to be available whenever I ask for it, immediately. And it also has to be the latest data. This data pops out of com port only every other second and is not available except the user needs this data also and so the UI merrily stores always the latest data.

I want to update the UI first and my reasoning was that it was almost :oops: acceptable to ask this one data from UI. I still think it almost is but your argument is also too valid :headbang:. I'd rather do this the right way and let the UI do what it is supposed to do. As I'll be thinking :lightbulb: of a better way to do this I'd still be more than happy to hear any suggestions as to where I should store this one value. I do want to steer clear of global variables. Should I just add one more thread (=loop) to handle this data?

To the next point, Q preview, the preview no doubt is the correct way of approaching this, the reentrancy I (for some long forgotten reason :wacko: ) tried to achieve only led me to problems. This went straight to top of my task list.

And finally the (G)OOP is at the top of my study list. Currently I still lack some insight about it and can't really visualize the way I should build the architecture, but in due time I will. I do hope I'll be ready already at my next project.

Link to comment
  • 5 months later...

Send data to the test sequencer using notifier, then sequencer will always get fresh data.

You can use queue for GUI if you do not want to miss the data, or again use the same notifier as for test sequencer.

Notifiers in general are good in situations where multiple recipients need access to fresh data.

RK

I think you caught my point very well and thank you for your answer.

As I told in my first post, I needed some data for test sequencer and this data needs to be available whenever I ask for it, immediately. And it also has to be the latest data. This data pops out of com port only every other second and is not available except the user needs this data also and so the UI merrily stores always the latest data.

I want to update the UI first and my reasoning was that it was almost  :oops: acceptable to ask this one data from UI. I still think it almost is but your argument is also too valid :headbang:. I'd rather do this the right way and let the UI do what it is supposed to do. As I'll be thinking :lightbulb: of a better way to do this I'd still be more than happy to hear any suggestions as to where I should store this one value. I do want to steer clear of global variables. Should I just add one more thread (=loop) to handle this data?

To the next point, Q preview, the preview no doubt is the correct way of approaching this, the reentrancy I (for some long forgotten reason :wacko: ) tried to achieve only led me to problems. This went straight to top of my task list.

And finally the (G)OOP is at the top of my study list. Currently I still lack some insight about it and can't really visualize the way I should build the architecture, but in due time I will. I do hope I'll be ready already at my next project.

827[/snapback]

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.