Jump to content

Aristos Queue

Members
  • Posts

    3,183
  • Joined

  • Last visited

  • Days Won

    202

Everything posted by Aristos Queue

  1. It works, but it involves a lot of data copying and reflection analysis. Does it scale sufficient for your needs?
  2. http://thecodelesscode.com/case/158 Enjoy!
  3. I did stress the word "plan". It didn't make it into 2014. Looks doubtful for 2015. :-( If you look at the 2014 new feature list, you'll only see one big ticket item -- the port to 64-bit on Mac. That ate into the dev team. There's another big project that is eating developers, making this kind of work very hard to get prioritized. They might not get publicity, but if they were in there, I would've gotten them into the Upgrade Notes. I'm sorry to disappoint, but I just don't have the wherewithal to do it myself and there just aren't many developers for me to "lean" on these days.
  4. I have a couple of XControls that I use for custom probes. I gave them to someone else to use, but they didn't want to use them because they'd heard stories about XControls in custom probes causing crashes. Has anyone else done this? Is there a problem I should be wary of? I searched the CAR database and didn't find anything, but my search skills might have missed something or sometimes customers know of issues that they've never had time to post, so I figured I'd ask. As far as I can tell, it works great.
  5. The data Y cannot be specific to msg class BB because the data class has to be filled in by the sender. By definition, it cannot be anything that is specific to the receiver, and therefore you can create class CC that is totally independent of the receiver. It also cannot be anything specific to the sender because the sender doesn't know the receiver.
  6. (I'm trying a new notation... message classes are double letters. Classes representing senders and receivers are full names, like Client or Server. I think this convention may aid communication.) Here is what you say you want to do: Client sends message class AA to server and says "please use message class BB to give me information Y". Server eventually is ready to send information Y. It creates an instance of message BB and sends that across the network. The challenge everyone runs into is how to instantiate BB on the server. But you don't actually need to do this. This is a technique that I should have put together sooner, but just flat out couldn't see until Dr. James Powell (user drjdpowell) walked me into it. Rephrase the problem: Client sends message class AA to Server and says "Please send me information Y using the standard protocol message CC. Inside CC, include the name 'BB' in its data." Server eventually is ready to send information Y. It creates an instance of CC and puts Y and the string 'BB' into the payload. CC is totally agnostic of any particular receiver. It's "on arrival do this" code [which in Actor Framework is called "Do.vi" but may be something else in your systems] says "Create an instance of BB and put information Y in it, then immediately call BB's "on arrival do this" code." Class BB is a child of CC, which means that you can have a method on class CC that uses the Swap Values primitive to easily move the data from one object to the other without a data copy. The CC class can be loaded on both sides without requiring any particular recipient classes to be loaded. Only class BB is specific to the receiver, and it is never on the sender's side. Also, ShaunR isn't wrong in his assessment about strings. The classes obviously cannot actually cross the network boundary -- no data structure can. The only thing that *can* cross the boundary is strings. So you have to encode the objects on one side and decode them on the other. If you use the process I laid out above, that allows you to use the built-in serialization mechanisms of LabVIEW classes. Or you can create VIs to encode and decode your data structures. This is a problem regardless of whether you use LabVIEW classes or any other data structure. My Character Lineator was created specifically to investigate the problem of serialization over time, where you have multiple protocols in the same channel. It is overkill for simple data movement that will never change between any given pair of client/server, but becomes increasingly necessary as your data serialization requirements increase, which they generally do over time. If you do take ShaunR's advice and build a string representation of your data, please review the CL and make sure you include all the necessary version checks, region encodings, and formatting control that your situation calls for.
  7. Door prize: Four copies of a brand spanking new poster from National Instruments featuring code-artwork from yours truly.
  8. National Instruments has created a GitHub repository to community source G libraries. This move is intended to be a test of a mechanism to enable customers to create customizations of NI source code and share those customizations with each other and for NI to be able to adopt some of those customizations into its core products to benefit the entire LabVIEW community. We are beginning with just three libraries: The Actor Framework, a library in vi.lib since LV 2012 The NI-GOOP Development Suite, a free toolkit add-on for improving LabVIEW class development The AQ Character Lineator, a library not yet in vi.lib to support serialization/deserialization of LabVIEW classes If this experience working with the community proves fruitful, NI may expand the number of our APIs that are part of this sharing. For more information, including instructions on how to access the GitHub repository, please visit this community: https://decibel.ni.com/content/groups/community-source-of-ni-code For details of how to get access to the GitHub repository and the license agreement covering this project, please visit here: https://decibel.ni.com/content/docs/DOC-37195 I want to make a personal comment on this new development: Opening up LabVIEW to more community participation is something I and a few others have worked on for many years. This is a major advance in that quest. We know that requiring a license agreement for participation is not a typical "open source" arrangement, but this is the best idea we have found to balance the desire of our users to improve LabVIEW while acknowledging that LabVIEW is for-profit software that gets used in sensitive industries. If you have particular objections to the license agreement, please open a discussion thread in the community linked above so we can discuss them. We believe most users will find this arrangement acceptable, but not everyone. I hope, though, that this can be a successful venture, and perhaps will serve as a first step toward more.
  9. Yes, yes, and after you've taken that semester of CS courses, you should attend shoneil's "RT is hell" masters course. :-) I didn't say DD was free. In the context of the discussion at hand, it isn't the expensive part.
  10. Oh, that... sorry... I was thinking about the shared clones reentrancy pool for subVIs. The prepopulation of the async pool just helps with performance -- you get all the allocation out of the way early and then start making calls. But if you run out of the pool, there's no danger of not being able to allocate more because of root loop, whereas there is with other types of allocations.
  11. Oh, yeah. But the crime isn't in making the accessors dynamic dispatch. The crime is not being organized enough to design the parent class. And that crime can have serious penalties for your code. Using dynamic dispatch for data accessors will generate massive data copies -- no inlining, no inplace memory optimizations. That does NOT mean you should never do it... it means you should do it ONLY if you truly need your child to define the data storage or get involved in the validation. Luckily, this is a situation that should almost never happen. Really? Really.... but that means you need to understand why you generally should not be doing it. You are violating the Liskov Substitution Principle. LSP says simply, "Any promise made by the parent class must be upheld by the child class." Having a child that *narrows* the definition of acceptable data values is an explicit violation of LSP. This rule must be maintained for most frameworks to work correctly. A child can accept a wider set of values, but it cannot accept a narrower set. Consider: I have a framework that calls your parent class. I read the documentation on your Write Value.vi. What does that documentation say? It says, "This VI accepts any positive real number and returns an error for negative numbers." Great! So I pass in 7.5. I have no idea your child class even exists. The documentation for the parent class says "any positive number". Now your child class gets created and gets passed into my framework, and it returns an error for any fractional value. WHAT? How could I possibly design for such undocumented behavior? A child is free to be *less* restrictive than its parent, but not more restrictive. For example, there are child classes that will happily handle NaN values but a NaN to the parent class returns an error. If I'm writing a framework that uses the parent class, I'm going to be careful to check for NaN up front to avoid the error, but if I am in a section of the code where I have the child directly, then I may pass NaN. So, when would it be acceptable for a child to get involved in validation? When you've documented that "the range of acceptable values varies based on the object in this wire, meaning callers cannot validate inputs ahead of time and must be prepared for an error from this function for any data value." LSP is not something that can be checked by a compiler. It is the contract that you write on the parent class that people who have never heard or seen your child class rely upon. Important safety tip: If you are the author of both the parent and the child, whenever you write code that calls the parent, you should pretend you've never heard of the child class. Write explicitly for only the parent class contract. If you do that then the bugs that come up are bugs in the child. Trying to factor into the calling code all the things you know your child classes might do will lead you to writing very poor performance code in the callers -- you will error check for things that shouldn't ever be possible, you will double check values that should already be validated, all because you cannot trust your children to uphold the promises. At the time you write your parent class, you should definitely be able to say whether or not a child is going to need to do additional validation. You might change your mind later -- and if you do, you can go change the terminals to be dynamic dispatch at that time. But don't pay the cost up front just because you might need it later. The dynamic dispatching is not expensive. The data copies can be. For most methods, dynamic dispatch is fine because the data passing across the border is inputs to some algorithm and outputs are computation results -- the outputs don't have to stay behind in the method VI. For property accessors, it's expensive because you're leaving a copy of the data back in the object, and no inplace sharing or other memory optimizations are possible across a dynamic dispatch call.
  12. Regarding your request: no can do because that isn't an error. A child class has no idea what fields its parent has. All the child knows is the API the parent exposes. How the parent chooses to implement that API is its business. The child might have its own functionality and decide to name a field with some name, and if that name overlaps, it doesn't matter ... the one that is accessed is specific to the context of the bundle/unbundle node. When writing a child, pretend you know NOTHING about the parent other than the public and protected member VIs connector pane and documentation.
  13. AEH? Yes. Debugging? Depends upon what you're benchmarking. Yes, I usually also turn it off, but some people want to see the performance in the editor and assume runtime will be even faster.
  14. Generally, yes, which is why I think they have the same behavior in this regard.
  15. shoneill -- I think that the handling of the "reference goes into something before leaving the loop" is the same for the class as for clusters and arrays. Can you check? I seem to recall that this was desirable as there was some use case for using the FIFO as an ID and not as a FIFO, or something like that. It isn't my area of expertise, just something I remember overhearing a while back.
  16. Part of the API is providing the interface that indicates what concerns the caller needs to have... in this case, that ordering needs to be a concern. The output terminal indicates that, whether it is a written by-value object or a reference object.
  17. ouadji: I never saw this post when it first went up... I have a problem with your benchmark. Can you redo it with the following modifications? 1) Change all the array constants and the numeric constant into controls and move them outside of the loop. 2) Put all those controls on the conpane of the VI. Put the indicators on the conpane also. 3) Create a caller VI that calls into your VI passing in controls (not constants) with the values. 4) Close the front panel (very important) of the subVI and do File >> Save All. 5) Now run your benchmark and see the performance. I do expect a significant performance boost but right now, your bench mark could be skewed by a whole bunch of constant folding and other compiler optimizations that wouldn't occur in real code. The above steps are basic requirements for any benchmark in LabVIEW.
  18. mje: Because we aren't really interested in "read only" ... what we're really interested in is "state dependence". If you have a pure by value object, if you only read the fields, there's no downstream dependence on what happened in that node. But if the object contains a reference, there's a timing dependency potentially. Consider an easy example of an object containing a DVR. If the first node just opens the DVR and reads a value out, the second node may be a writer node that needs to guarantee that it doesn't write the value until after the read is finished. With a by value object, if you forked the wire to a reader and a writer, it wouldn't matter which executed first because each branch of the fork is working on an independent copy of the object (LV's compiler may optimize those copies away at its discretion). But with a reference, each branch is working on the same copy, so you may need an ordering between the read and the write, so containing a reference turns the whole object into behaving like a reference and thus needs an "object out" terminal on every node, regardless of the work that node does.
  19. Populating the call pool is required if you're making synchronous subVI calls and not going through the asynch call by reference node. The synchronous subVI call has better performance (because LV knows ahead of time exactly what subVI to prepare to call and all it needs is the memory instance, whereas there's a lot more unknowns around any of the call by ref nodes).
  20. Yes. If the parent class contains the value in its cluster, the child class already has that value in its cluster, but you cannot access it through the bundle/unbundle nodes... it is private to the parent and the parent must expose a VI to let children access that value. What you should do is add two protected scope VIs to the parent class to do Read and Write of the value -- those two VIs should NOT be dynamic dispatch. The elements in a child's private data control ADD to the elements in the parent's private data control. If you miss this point, you will have many bugs throughout your LVOOP code.
  21. I have a personal convention for indicating this, but many people hate it: remove the "object out" terminal for any subVI that does not modify the private data. If it has an "object out" then it modified the data. If it doesn't have an "object out" then it didn't modify the data. Q: But, oh, how will we railroad track our VIs when calling multiple read methods?! A: You won't. You'll call them in parallel like God and dataflow intended. In my personal code, the only time I'll have an object out for a read-only method is when the class contains a refnum -- because by reference, you cannot be sure anything is read-only, and thus there is always a data dependency between function calls.
  22. An example of how to safely set up the ACBR call is in vi.libActorFrameworkActorLaunch Actor.vi in LV 2013 and later. Thanks to drjdpowell for catching that one -- myself and the rest of the AF community missed it.
  23. CharlesB: You'll find that the class retrieval has a really nasty performance curve. There really isn't a good solution until 2013... I tried hard to find one, but hit too many performance issues with every other approach, and finally cut a new interface into LV. (To be clear... it does work... and if you don't have a tight loop, it works fine. It's the performance that was the issue.)
  24. As soon as possible, but not any time soon. There is a massive multi-year project standing in the way that has pulled in many developers, including myself. I happen to agree with the Powers That Be that this other project is a higher priority that will do more for our customers than interfaces would, but I still grit my teeth every time I'm working on a project that needs good interface design. It is on the roadmap, just not on the timeline I had hoped for when we released classes originally.
  25. I think I'm in love: Flowing from my brush Glowing on my screen Four lines readable in any order The essence of thread safety -- Qi, the scribe http://thecodelesscode.com/case/126
×
×
  • Create New...

Important Information

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