Jump to content

Jon Kokott

Members
  • Posts

    186
  • Joined

  • Last visited

  • Days Won

    4

Posts posted by Jon Kokott

  1. I use master/slave all the time. Granted I don't use them with notifiers, but I consider them slaves because all their messages come from a single source, their master. In this example the Mediator loop is the master and the StgCtl and Joystick loops are slaves.

    The only thing in common with NI's master/slave architecture and your example is that you both call it a master slave architecture. You use unlimited sized queues for messaging => Losslesss messaging, NI's template offers lossy messaging.

    I think your code is similar to what a programmer might do to solve a problem, whereas NI's template is a solution searching for a problem.

    ~Jon

  2. If anyone has ever used the master/slave pattern (and gotten paid for it) where did you use it? It seems like its strictly academic. I wanna see a master slave pattern that uses more than one slave. If you have a master slave with only one slave, it can be drop in replaced with an SEQ using lossy enquue (and probably be better since you can choose to dequeue or preview instead of wait on notification and clear.)

    ~Jon

  3. I'll just throw this out there since I just did it and saw this post:

    I initialize a U32 Array (of size 1000) representing the string lengths of every line in the string indicator to length 1. I create a string of 1000 CR constants and store it in a DVR. Every time I concatenate to the log I get the length of the string I'm adding, build it to the length array, chop off the zeroth element of the array, and string subset based on that length.

    This approach will NOT limit the string length, but will limit the lines displayed. The scroll will simply stay at the position it was left at, so keep "scrolling." I add some functionality for stopping the "scrolling" by canceling the updates to the display during a mouse down, restarting during mouse up. The actual display updates were performed using a single element queue on a 100 ms timer (lossy enqueue)

    I've had success with what I consider a pretty unreasonably large string, I actually made the lines retained smaller because the scrollbar was so unmanageable when trying to go back.

    I should also note that this will only work if you know your log postings are one line and one line only. If you want to post a chapter book, best of luck with something else.

  4. Ack I didn't look closely enough. The output and input match. I saw that the Initialization vector/Cipher key were converted to bin from ASCII text, and I assumed that the message was also exhibiting this behavior. I suppose converting the cipher key from ascii is fine, it just through me off as I put in the correct sized key/vector and the function still output an error on cipher size until i found that it was converting from ASCII.

    So the only change I would realistically like to see is that the default display for "message in" on encryption and "plaintext out" on inverse cipher be of the same display style so I don't fool myself again.

    Again I really like this, I will use it on my config files so no one will try to mess with any binaries without me knowing again.

    ~Jon

  5. I like this a lot.

    One thing, for AES encryption the input text is immediately converted to ASCII hex. I think this might be a mistake. This results in putting plaintext in, cyfering it, then invcyfer does not result in the original text, it results in the ASCII hex representation of the original text. This is data bloat, and would require an additional converter to return the original text.

    I would also support some kind of a primitive method of padding the key and initialization vector for ease of use.

    ~Jon

  6. A configuration file would be useful if you wanted to change the value of the constant, especially, for example, in a built application. If I want to store a constant, let say "h" or the "plank constant," I would be better served with hard coding an actual constant. Obviously that would never change, and the code damn sure communicates that. If you have an application which requires the "constant" which shouldn't even be called a "constant" to change, then use some other tool

  7. If it's a value that never changes and you don't load, a VI with a constant in it could be set to inline, thus providing the same (similar?) overhead as a constant with the benefit of changing the value one place.

    Tim

    I feel this is the best way to represent a project constant. It is obvious in the calling code that you are accessing a constant. Using globals, FGs, imply that data is being stored and changed. Even if you put a comment in the FG or global it still doesn't guarantee abuse of the constant, and an outside developer is left to finding all instances in the event that something goes wrong.

    An inline SubVI with a constant IS an immutable object. So what is the best way to represent an immutable object (I.e project constant)? how about with an immutable object?

    • Like 1
  8. Yeah thats pretty much where I got this idea from. I actually started doing this with a queued command class operating on person with a while loop and the "actionl.vi" in like 8.6. If you look at the actor framework, thats pretty much the core operation. When DVRs came out I looked at the IPE as a way to "walk around" with the shift register, and use that same architecture. I find the DVR implementation easier to debug in most cases, the only issue is that the recursive call does make debugging a little harder. I usually wait till i need that feature, or don't do it at all.

    FYI i've benched using a DVR vrs a dynamically launched process running off a queue (messaging system) (in 2011) and the messaging system is 4x faster (which I wouldn't have guessed.) Here is the trade offs for using a DVR in this fashion vrs a messanging system:

    Messaging:

    • Slower initialization (like 10 times slower, this only applies to running with a 2011 run async node)
    • Faster command operation (about 4 times faster) this is a more important time to be fast
    • harder to debug
    • calls can be made directly in the event structure without worry of blocking the user interface since all we do is enqueue some data.
    • 2 references to deal with (the queue reference, and the async node reference)

    DVR:

    • Easier to debug (of course this is just my opinion)
    • calls are "blocking" as in when the function finishes its really done. you might actually want this feature for an API since the user wants to know when the function completes for synchronization purposes and an additional reply layer will be required for a messaging system.
    • much faster initialization of variables. This will be better for short lived objects.
    • This type of API I've found is much easier to deliver to people who aren't totally into .lvclasses, and advanced architectures. Daemons scare people sometimes.

    In my opinion, the current "state of the art" for labview IS messaging systems. If you want to drive your coding by performance (maintainability is first, but I think I've shown these are basically equivalents as far as that goes) then messaging systems are better. DVRs are certainly not useless, and there are lots of good reasons to pick them. They just work a little differently.

    I find myself using both. I prefer to represent hardware as a DVR, but most other software operations are synchronized with other types of patterns. I feel like messaging is inherently event based, and DVRs are inherently polling mechanisms. The different types are better for different things.

    ~Jon

    I might take back that statement about being 4x faster for messaging. I'm not sure the bench I did accurately measured that particular operation. The timer didn't account for the multithreading involved.

    ~Jon

  9. This is basically the best thing I've come up with for dealing with references. This could easily be converted to a messaging system because it acts on a command class and not a directly exposed API. Of course person could have its own class hierarchy but for the purposes of this example I didn't go into that.

    Block Diagram

    post-17025-0-33288400-1314146944_thumb.p

    All Commands Call "Do.vi"

    DO.vi unwraps the In place element structure, and calls the dynamic dispatch instance of "Action.VI" which is in the command hierarchy

    Methods of "person.lvclass" are called within the individual "Action" VIs

    MultiCommand can call multiple commands without leaving the in place element structure. here is its block diagram, it is a recursive call

    post-17025-0-56480000-1314146945_thumb.p

    Here is the output of this group of calls, it shows the unwrapping/wrapping of the reference

    post-17025-0-03947800-1314146945.png

    I think this is basically the most extensible way to do a by reference API

    ~Jon

    DVR Intervace 9p0.zip

    • Like 2
  10. Basically what you want is to give your user the ability to define when consecutive methods should be acted on atomically.

    The best way I have of achieving this is by creating "command" class hierarchy. All of your "methods" are dynamically dispatched by the command class received. One of these commands is actually a recursive structure which contains an array of type "command." This is kind of a pain in the ass to program but is highly flexible.

    So to recap:

    you have a Class which is represented BY REFERENCE.

    all "methods" ARE BY VALUE.

    you 2 wrapper functions which are called "execute one command" and "execute multiple commands" the only difference between these two is that one takes an array of command to operate on the object, and the other only takes one.

    All calls will consist of populating the "command Class" with its associated data, then calling the generic execute one command VI.

    Keep in mind that this will require that the dynamic dispatch "command"::DO.vi to be reentrant.

    Option 3 (not shown) - Create a DVR reference and place that inside the lvclass private data. This means that you can't access the private data of the class without dereferencing the DVR. It also means that the public API never exposes the DVR.

    I use this option frequently and it seems to scale well in that I still have dynamic dispatching but my data is byRef due to the DVR.

    Man I just had a big discussion about whether the DVR goes inside the class or is of the class.

    I prefer the class to be A DVR of the class. Its important for the reason that mje describes above, and I think it unnecessarily obfuscates the operation of the class. By value or By reference is a fundamental enough concept that the user should know the "rules" of using the class. The API itself being by reference certainly tells you something about thread safety.

  11. "UI Initializer" is definitely a decedent of "UI Command Manager." What you are looking at is a very important concept in lvclasses. There are several ways to view the class hierarchy. The most common is to find the class within the project explorer, right click on it, and select properties. in the subsequent dialog, select the "inheritance" option. this will show you the class hierarchy. Given what you are showing here, there will likely be many classes within the hierarchy.

  12. If you dig into the *real* reason people use reference data, usually it amounts to "it's easier to implement" or "I don't know how to solve this problem without using reference data."

    Considering how well developed by reference programming is (in general computer science as well as labview) I wouldn't say that at all. Atomic actions on a piece of data can be done in more than one way, and there are performance/maintainability tradeoffs when choosing between say an Actor framework and something strictly by reference. If anything you should know both and understand the design constraints you have imposed on yourself before deciding that one or the other is the best.

  13. Personally, I do not care for singletons anywhere in my code. To me, not having a wire is a disadvantage. This is because establishing the scope of a given object becomes difficult. I've debugged enough code from others and figuring out where all the FG (singletons) are is PAINFUL when there are 30 different ones called in 1000 places. Singletons have awful connector panes in many cases (using a variant or class input output can fix this.) Lastly, thinking you'll only need one of these objects WILL bite you one day, its only a matter of time, and it is (usually) nontrivial to convert it to a by reference implementation.

    So here is my opinion of when it is appropriate to use a FG/singleton:

    1. Configuration information. This applies to any "Variable" that you set ONE TIME and then read throughout the application. If you want to change that info, don't use a singleton.

    2. I don't have anything else, People do use them for other things such as a "global Stop" which I'm willing to deal with, but I'd rather use event based stopping.

    When to use a DVR:

    If you deem it appropriate to use a by ref pattern, DVR is prefered to SEQ/CBR nodes because:

    It runs the fastest

    it has a clear lock/unlock scope within a method.

    My 2 cents.

    At the end of the day you should probably pick the implementation that works best for you and your team in terms of understanding and maintainability. If noone knows what the heck a by reference pattern is but FGs "click" for them, either spend some time learning about different ways to program or do what works. There are lots of people who have used FGs in large applications which have been maintained over a long period of time. I simply believe that they are obsolete today.

    ~Jon

    ~Jon

  14. They are not the same. A single element queue can be used as a mutex in a by reference style of code. (dequeue locks, enqueue unlocks.) Using a notifier would not allow you to mutex correctly since you cannot wait on notification and cancel it at the same time. You would be required to test that the waited on notificaiton message was identical to the canceled notfication and internally include a modification metric to ensure that you have the correct data in instances where actual data does not change, and retry if you didn' t get the reference (practically speaking I wouldn't even try.)

    a notifier would behave the same as an SEQ if you ONLY used the lossy enqueue and preview queue funtions. I'm not sure which one would perform better.

    the best performer in this type of by reference structure is the DVR (data value reference)

    ~Jon

  15. User-defined menu entries in the File pull-down menu are linked to VIs created in the [LabVIEW]\wizard directory. Do you have a 'wizard' directory in your LabVIEW 2010 install?

    Correct, this was an option installed by OpenG. I was mistaken/(completely forgot you could add items to the file menu) in thinking it was something NI installed.

  16. You are opening a VI using VI server, so the VI must not be reserved in the hierarchy allready. Make sure that you do not have a strictly typed VI reference (of the VI you are trying to load.) in any vi within the application space.

    ~Jon

    edit:

    I think that this also means that you cannot have the VI in the hierarchy set to "Reload for each Call" or "Load and retain on first Call" I believe that those will reserve the VI as well. for some reason I don't think that Load with callers reserves it but I'd have to double check that.

  17. I've been evaluating LV2011 and noticed that a feature from 2010 does not appear to be available in 2011.

    2010:

    when in a .lvproj:

    File->Locate in project

    will locate the current VI within the project hierarchy.

    2011 (and older than 2010 versions of labview) appear not to have this. I do use this and am somewhat disappointed

    Does anyone know why they would take that away?

    ~Jon

  18. How many NICs do you have on each PC?

    I'm assuming you are running windows, and connected to an internet gateway/LAN on another connection.

    One thing that might help you is changing the interface metric of the individual NICs on each PC. Put the ones used in your setup as a 1, and all the other ones 2 or higher. This will probably mess up your internet connection, or make it unbearably slow when it works.

    ~Jon

×
×
  • Create New...

Important Information

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