Jump to content

Jon Kokott

Members
  • Posts

    186
  • Joined

  • Last visited

  • Days Won

    4

Everything posted by Jon Kokott

  1. You need to just code it with both. They don't behave the same, preview runs away. Make like 3 slaves operating on a notifier, and then 3 on a queue. they will not produce the same results
  2. Definitions: Master/slave - NI's template implementation. Incorrect. This only works if you have ONE dequeue place. If you were to try this with multiple "slave" loops it would immediately break down. A queue (even size one) will not perform identically to a notifier. So I'll ask my original question again: Does anyone use the master/slave template pattern? You MUST use a notifier as the transport. You MUST have atleast 2 slave loops. You must RELY on lossy transmission (ie its a better solution than a lossless transport.) If that's not the case I won't be satisfied as it is just a different way to solve a problem that could be done using a different, better, pattern. Basically I think the template is terrible, and its actual use cases limited. Using a notifier for commanding one "slave" is a drop in replacement for an SEQ (What Daklu was talking about) solution. For whatever reason NI has labeled it a "fundamental" concept, but it is really just academic. ~Jon
  3. We are in disagreement on this. The implications of having a message never be received are far reaching. It would greatly affect the construct of the underlying code. Notifiers are one to many, queues are not. Notifier slaves will scale, QSMs (or any dequeue) operator, will not scale to other threads. The notifier will "wakeup" all waiters ONLY once, but only with the latest data. You cannot use a queue to do this, and you cannot do it with an event structure (again lossless transmission of messages.) The template is for some special cases where only the most recent data is important, and the older data can be thrown away. Not the same as the template, event structures are lossless transmission types. Honestly, I'm starting to think that the NI "master slave" template, isn't even a master slave pattern. Somebody at NI read a CS Article and created this template. Subsequently its been taught in countless Labview Seminars, then seldom used, or worse, used with the assumption that the message transmission is loss-less, which it isn't (probably only "guaranteed" by fictional windows timing).
  4. 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
  5. OK, where did you do that? Everyone can show an example of where you "would" use it. But then we all have a more complex system and elect not to use it. Every time I've used this model i've been able to do it with an SEQ.
  6. 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
  7. Does anyone actually use the master/slave? I find it to be useless. Actually I think notifiers in general are pretty useless, every time I've used them I've been "trying" to use them, and ultimately just find them to be less useful than other patterns. ~Jon
  8. create the method in parent class then on the child class right click: new-> VI for override select dynamic dispatch instance to override there.
  9. 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.
  10. 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
  11. 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
  12. 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
  13. 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?
  14. 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
  15. 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 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 Here is the output of this group of calls, it shows the unwrapping/wrapping of the reference I think this is basically the most extensible way to do a by reference API ~Jon DVR Intervace 9p0.zip
  16. 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. 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.
  17. "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.
  18. 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.
  19. 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
  20. 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
  21. https://decibel.ni.com/content/groups/niweek-2011?view=documents
  22. 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.
  23. Hmm, I wonder where that shortcut in the file menu came from. I think it is in ONLY LV2010 SP1 for me. I think its largely irrelevant based on what you say, I'll just start using the hotkey. Thanks, ~Jon
  24. 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.
×
×
  • Create New...

Important Information

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