Jump to content

Does wrapping the dequeue primitive in a sub-vi require re-entrant execution


Recommended Posts

I recently went through my code wrapping all my dequeue prims inside Sub-VI's which I've called Dequeue Message.VI. It's a simple wrapper that handles some basic errors such as queue reference loss and prettys up the unbundle by name code a little bit.

I noticed that messages enqueued weren't getting through to the dequeue. So I poked around a bit and discovered that the reference inside the Dequeue Message.VI was different to that outside. My best guess was that somehow because I was using multiple instances of this Sub-VI concurrently, when debugging, I was looking at a different instance of the Sub-VI. Even so, they shouldn't be "losing" their message, my best guess was somehow the multiple instances were causing the Sub-VI to lock. Which sounds like bs even to myself as I was under the impression that every time you dropped a Sub-VI into code, the compiler effectively inlined another copy of that code. In other words, from all my understanding, it should be possible to drop my Dequeue Message.VI into any number of loops and each dropped copy be independant of the other.

Anyway, just to see what happened, I changed the execution of "Dequeue Message.VI" to allow re-entrant execution and allocate different memory for each clone. Lo and behold, it worked.

Can anyone explain why this is so to me? Also, if I've done something crippling obvious that means I don't have to allow re-entrant execution, please let me know.

Edit:

I've pulled the code apart and created a scratch pad type test where I just passed a message from one loop to the other. It behaves as expected, even with the dequeue hidden inside a sub VI. I'm completely stumped why, in my main set of code it's hanging at the dequeue...

Edited by AlexA
Link to comment

Sorry about the second post, I had to refresh page so can't edit my OP.

I've managed to narrow down whats causing the lock. When the "Dequeue Message.VI" is placed on a block diagram in two separate while loops and asked to operate on two different queues in your typical asynchronous fashion, it will lock. So I guess I've answered my own question (it seems the only way is to make it re-entrant), but now I'm left wondering why this should be the case? Also, is the answer (while avoiding re-entrancy) to make the message handler sub-vis into methods on a message class? I don't know why I'm scared of re-entrancy, I just feel like maybe it will introduce some bugs that I can't predict (due to my lack of knowledge).

On a related question. If I take the approach of making the message handling code OO, would the resulting memory footprint be similar to multi-clone re-entrant execution? Or somehow similar to single memory instance re-entrant execution? (Which I'll admit I haven't yet tested).

Link to comment

I was under the impression that every time you dropped a Sub-VI into code, the compiler effectively inlined another copy of that code. In other words, from all my understanding, it should be possible to drop my Dequeue Message.VI into any number of loops and each dropped copy be independant of the other.

This is incorrect. By default no sub vi inlining is done. If multiple loops are attempting to execute the same non-reentrant sub vi, loop 2 will remain blocked until loop 1 finishes that sub vi.

I don't know why I'm scared of re-entrancy, I just feel like maybe it will introduce some bugs that I can't predict (due to my lack of knowledge).

Reentrancy is safe as long as you understand a few rules. It might help you understand what is happening if you create a sub vi (Inc.vi) that increments an uninitialized shift register and experiment with that.

First, each vi is allocated a data space in memory. A non-reentrant vi has a single data space that gets reused every time it is called. When you put Inc.vi in multiple loops the shift register acts kind of like a global value. Each loop, though independent, increments the same value. That's because all the loops are accessing--and incrementing--a value in the same data space.

Using the "shared" reentrancy option means if LV discovers Loop A is blocked waiting for Inc.vi to finish executing in Loop B, it will allocate another data space for a new instance of Inc.vi. You might have 7 loops using Inc.vi, but during execution LV might only require 3 instances of Inc.vi to prevent blocking. Note you cannot associate a specific instance with a particular loop. The natural consequence of this is that you will not be able to predict the value on the shift register for any given Inc.vi execution.

Using the "preallocate" reentrancy option does what you originally expected was the default behavior. Every instance of Inc.vi on a block diagram has it's own unique data space in memory. The shift register value will increment only when that sub vi on that block diagram executes.

On a related question. If I take the approach of making the message handling code OO, would the resulting memory footprint be similar to multi-clone re-entrant execution?

Making the message handling code OO doesn't affect how many instances of the vi are in memory. That is still determined by the vi properties execution options dialog.

Or somehow similar to single memory instance re-entrant non-reentrant execution?

Reentrant in LV implies multiple instances in memory. "Single memory instance reentrant" in an oxymoron.

If I take the approach of making the message handling code OO...

There are several OO messaging frameworks already published that have been around for years. Before rolling your own you might want to look at them.

-Actor Framework

-LapDog

-JAMA

Searching for any of them on LAVA will turn up a bunch of information.

Link to comment

Hey Daklu,

Thanks for the insight. I've had a look at Actor Framework but concurred with someone who described it as not being suitable to drop into an already established project without massive re-engineering. I wanted to have a look at LapDog but when I downloaded it. It doesn't seem to run correctly. Double clicking or running the .vip package will cause the VIPM package handler window to open but almost instantly close again.

I was trying to install it for LV 2011 if that makes any difference.

Once again, thanks for your insight on re-entrancy!

Alex

Link to comment

I wanted to have a look at LapDog but when I downloaded it. It doesn't seem to run correctly. Double clicking or running the .vip package will cause the VIPM package handler window to open but almost instantly close again.

Sorry for going off-topic, but I haven't encountered this behavior recently.

Which VIPM version/build are you using?

Which LapDog.Messaging package version do you have?

Does anything show up in the VIPM error log? (c:\ProgramData\JKI\VIPM\error)

You might try deleting any LapDog.Messaging packages from VIPM's cache (C:\ProgramData\JKI\VIPM\cache) and then reinstalling the package.

post-7603-0-78346800-1329164952_thumb.pn

Link to comment

Hmmm, I've read over the thread associated with LapDog's release on the Lava forums, and after playing with setting up and sending messages around using LapDog, I can understand the appeal of "strict" security implicit in using message classes to send data around, but it seems that it's a safer OOP duplication of variant type messaging?

Please bear in mind that the above is in the context of my very poor understanding of OOP, as such there may be some inate power of OOP that I've missed when playing around (more than likely).

Link to comment

but it seems that it's a safer OOP duplication of variant type messaging?

Yep, that's a fair assessment of the bare framework. It's intentionally similar to string/variant messaging so people who are not familiar with OOP will not be faced with a steep learning curve. As a developer gets more familiar with LVOOP they can incorporate more complex OO patterns into the messaging system. It's not intended to be a complete messaging system that meets everyone's needs.

there may be some inate power of OOP that I've missed when playing around.

It's not obvious to those not familiar with OOP, but the power comes from the extensibility of classes and the ability to customize the messaging system for your environment... or even for each project. (All my projects contain custom, application-specific messages in them.) Need to eliminate the possiblity of run-time type mismatch errors? You can do that. Willing to accept the burden of testing for type-mismatch errors in exchange for faster coding and looser coupling? You can do that. Want to protect a queue so there is no chance another developer accidentally releases it in his code? You can do that too. Discover you need to replace a regular queue with a priority queue? Pretty simple to do.

And if that doesn't convince you, hey... the reentrant flag is already set for you. ;)

Link to comment

Hahahaha, Thanks Daklu. I do appreciate the work that's gone into LapDog, and it does seem like a really elegant and light messaging system. Unfortunately re-engineering my code (again) is being swiftly pushed down the priority list in favour of moving onto other more pressing projects. Hopefully I can come back to it at some point, and I'll definitely consider using it as the back bone of my future projects.

Link to comment

As a fellow newcomer to LVOOP & LapDog I just wanted to plug them both :thumbup1: !

My previous code involved some use of the Variant + String messaging and a bunch of plain old LV-Level1 code from myself and the previous demented LabView guy around here (LabView, I have come to KNOW, is the most commonly used programming language among lunatics...myself included).

Anyhoo...My 2 cents is that LapDog may be the best teaching tool for LVOOP out there! It allows me to keep parts of my code that use message-driven case structures with minimal adaptation. Once I have exchanged LapDog for the old Queue I can add a "default" case to accept the message object and dynamically dispatch it! That's great for VIs where I don't have time to wrap every case into a method or I need to adapt to somebody else's code. Also, for cases where you just need a single value(int, bool, string) you can just use the "native" message types.If you use a lot of cluster-variants in the old code it may be less feasible to replace but most of my messages had the string doing all the work.

Link to comment

My 2 cents is that LapDog may be the best teaching tool for LVOOP out there!

Thanks for the shout out and I'm glad you're finding it useful. (My personal belief is the best teaching tool is all the code you throw out when trying to figure out how to do something.)

If you use a lot of cluster-variants in the old code it may be less feasible to replace but most of my messages had the string doing all the work.

My sense is if the application is already well structured, replacing string-variant messages with LapDog would be fairly straight forward and can be done incrementally. (Though I've never actually tried it.) Where it gets tricky is if the application uses a lot of globals, local variables, control references, and things like that for communication. (I have tried that.) It's really hard to refactor one section without changing a lot of other sections as well.

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.