-
Posts
1,969 -
Joined
-
Last visited
-
Days Won
172
Content Type
Profiles
Forums
Downloads
Gallery
Posts posted by drjdpowell
-
-
I am thinking it might be better design for Actor B to send the data to Actor A along with the next step it should do. That way Actor A only knows two things: How to ask for data and how to process data when received.
I would have Actor A attach some kind of token to its request to Actor B, that Actor B would send back attached to the requested data. This token would contain the next step for A to do. This way the code for A is all contained in A, and B can be more generic and service requests from multiple actors.
In the framework I use, which like Lapdog uses text identifiers on messages, I usually do this by configuring A’s request to relabel the reply from B:
Here, A will receive back a message containing B’s data, but with the label specified by A (overwriting the label set by B).
-
Query: Isn’t it the DVR (or SEQ or other similar reference) that is an alternative to the Action Engine’s uninitialized shift register, rather than LVOOP? LVOOP is by-value, and you need something by-reference to stand in place of an action engine. The DVR is by-ref and can be shared among VIs with different con panes, in contrast to the shift register that is constrained to one VI.
-
1
-
-
For example, here's a screenshot from the 2012 QSM project template.
The thing that strikes me about that picture is, first, the fact that the queue has two writing processes, and second, that subactions of handling a message are treated as new messages for the queue. I agree with you about the problems of this, but don’t think that this is best communicated by arguing about how to define the differences between two very similar acronyms. I feel the same way about the “Action Engine”/FGV thing; it’s not really very productive.
I think it would be better to identify and talk more directly about the issues of message ordering and perhaps introduce more illuminating terminology, for example the concept of a “critical section”, or the database-transaction concepts of “consistency” and “isolation”. The “Initialize” transaction is a critical section, and because it isn’t protected as such it isn’t isolated from other transactions. Adding a different (non-FIFO) transport, that may switch the order of the two subactions, would also prevent it being consistent.
Note, btw, that a Get-then-Set transaction on a FGV/AE is also a critical section, and because it isn’t protected as such it isn’t isolated from other transactions. Thus, these concepts are more widely useful than the definitions of QMH/MHL.
— James
-
Rather than argue the difference between a queued message handler (built from from loop) and a message-handling loop (sitting behind a queue), would it be better to focus on the difference between a message queue with only a single enqueuing process, versus one with multiple writers in parallel that could lead to race conditions?
-
I still believe QMH is a poor name. It identifies the message transport's implementation--a queue. The transport's implementation is irrelevant to your definition of what a QMH is. Furthermore, I believe the transport's implementation is irrelevant to any well-written message handling loop.
A “queue” is different than a specific implementation of a queue, such as the LabVIEW in-built Queue. User Events also involve a queue, as do things like TCP or Network Streams and the like. In contrast, things like Notifiers do not. So, “QMH” does not specify the transport implementation.
Re QSM/QMH/MHL: I note that “queued-message handler” is ordinary English, while "message-handling loop” only makes sense if one understands the programming-specific use of the word “loop” to mean repeated code. “Queued state machine” only makes sense if one uses "state” in a very strange way that doesn’t have anything to do the state of anything. So I like “queued-message handler”.
BTW, one can make a QMH that is composed of a pool of MHL “workers”, so those two terms are not necessarily interchangeable.
-
Thoughts on just watching it:
1) More pictures; fewer words.
2) I suggest starting with the Message-Handling Loop or QMH (that people will be familiar with) and talk about what restrictions would make this an Actor:
— communicates with other code/actors ONLY via messages to this SINGLE loop. No by-ref data sharing or other communication methods.
— no global addressing (eg. no “named” queues)
3) mention “high cohesion and loose coupling”; an actor is a cohesive unit that is loosely coupled to other actors.
-
Thanks for the replies guys. drdjpowell, is my attachment correct? Reason I ask is it seems the tunnel went to "use default if unwired" automatically and I did not have to select it but usually I do.
Yes, that’s right.
-
If you want to update the graph only after events come in, but don’t want the overhead of updating every event in a “burst”, you can put a “-1” constant inside the timeout case and wire it back through shift register into the timeout, and set the tunnel out to “Use default if unwired” so that the timeout is zero after any event other than timeout.
-
1
-
-
My Mac is pre-retina, but have you tried playing with these settings?
-
I know, people should be trained not to stop the execution that way, but this will happen. I don't want to hide this button, since it might be necessary to kill the program from time to time during development. So I'm looking for another way to handle this.
I generally hide the toolbar on the front panel. One can still access the hard-stop button by opening the block diagram. I also usually capture the “Panel Close?” event and use it to trigger ordered shutdown, so a User can hit the X button to stop the program correctly.
I’m not sure there is an easy way to clear the lock if this happens, other than restarting LabVIEW.
-
Why not just wait until you come back when the others will have been addressed too?
Just in case someone is urgently needing this bug fixed.
-
I’m about to go on holiday for two weeks, so I’m going to post a CR version with just the bug fixes made by James McNally, leaving other issues for later.
-
I may be missing something, as I haven’t used other OOP languages, but can't we already create “constructors” and “destructors” and get polymorphism through polymorphic VIs? Polymorphic VIs could do with an upgrade to interface more nicely with dynamic dispatch methods, but otherwise what are we missing? “Overloading” is not interesting to me because I don’t specify functions by typing their names.
— James
BTW, your “Singleton” example isn’t a singleton; I can easily call the constructor multiple times and make multiple instances of the class. Also, I didn’t understand the “DVR cannot be used for dispatching” issue; I tried making a child class with an override and it worked fine.
-
I scored 60% coverage and passed (barely).
-
1
-
-
Looks good to me. Any other changes before I make a new VIPM package?
-
Question is how do I get the actual values of these lookup tables rather then the indexes to the fields of the lookup tables?
You need to do a “JOIN” of your lookup tables to the main table.
-
Why are classes D and E not children of C, if they are to use C’s method?
-
1
-
-
Thanks.
-
Still down. I’m going to try “Report to Moderator” on this post.
-
Playing around with Queue tester, it was interesting how most of the slow queue performance is due to attempting operations in parallel. In a striped-down test (statistics removed) it was about 8 times faster if it was run in the UI thread (forcing serial access). It was 0.6uS per element on my relatively slow processor.
-
I noticed that sequencing the two “Enqueue” operations (by connecting the error wire) increased the queue performance greatly on my system.
-
I didn't install it using VIPM though.
How did you install it?
-
What I wanted to do now is to code a simple standalone viewer for the database so I can see what my testrig is doing while I'm in my office/at home. The problem is: when I try to run the compiled code, it simply does not work...
It compiles and runs nicely, I have no access to the database though. Nor any error message. And I didn't even try it on another machine, it's still my lab-pc running Win7 and LV2011.
Do you mean you are building an EXE executable? I would suspect the problem is not getting sqlite.dll included. Check the “Preview” page of the build and see if sqlite.dll is installed under “data”. Sqlite.dll is part of the “Connection” class library and thus should be included, but I noticed just recently that the library, when installed with VIPM, loses it’s connection to this file. If this is the problem, you can fix it either by opening the “Connection" class and fixing it to include sqlite.dll, or adding sqlite.dll to the “Always Included” section of the build spec.
-
Needing to capture a peak value. Not willing to rely on sofware timing for fear of missing the actual peak in between LabVIEW read cycles.
Can you provide a hardware trigger at the high point of your pulse peak? Then you could trigger the DAQ read at the exact peak.
Feedback Requested: Daklu's NI Week presentation on AOD
in LabVIEW General
Posted
BTW, a Database is not a good example to use for considering “actors”; a database is already well-designed for handling concurrent access, so someone reading may not see much value in introducing actors. Instead, how about a piece of hardware that can only do one thing at once, but may be needed by multiple concurrent processes. A part-handling robot, for example. An actor that handles all interaction with the robot can rewritten to mediate concurrent requests, perhaps through some kind of “transaction” system. Eg:
ProcessA —> Robot: “Request robot transaction"
Robot—>A “Transaction Started"
ProcessB —> Robot: “Request robot transaction"
Robot—>B “Busy; you are in job queue"
ProcessA—>”Do action 1"
<robot working>
ProcessC —> Robot: “Request robot transaction"
Robot—>C “Busy; you are in job queue"
<robot working>
Robot—>A “Action 1 Finished"
ProcessA —> Robot: “End transaction"
Robot—>B “Transaction Started"