Jump to content

Tomi Maila

Members
  • Posts

    849
  • Joined

  • Last visited

  • Days Won

    9

Everything posted by Tomi Maila

  1. Thanks Mike, your proposed solution makes sense to me.
  2. I wanted to test the for loop trick with N=0 for getting a default value of a LabVIEW class instances. I tested with LV 2010 on OS X. It doesn't seem to work at all. See the attached picture and project for LV 2010. In the top wire I would expect the wire to have a default instance of the Parent class but it has a LabVIEW Object. The second wire has Child class instance default value as expected. The third and fourth wire have Parent class default value when I was expecting Child class default value for both wires. Did I understand something incorrectly? Default Value Propagation Fail.zip
  3. Just had a strange behavior with a property node. Class wire was wired to a property node with 4 read properties. The value of the class wire (non-DVR) was right according to the probe just before the property node. There was a private data called DBL one of the read properties accessed. When the property node executed, the accessor was executed, but the object flowing from the input terminal of the accessor was the default value of the class, not the value of the wire connected to the property node. The property node returned incorrect value i.e. the default value. When the property node was replaced with a read accessor, it worked properly. When I replaced the read accessor again with a property node, it worked properly. So it seems that there is some, possibly optimization, that takes place, and the result of which, the accessor does not get executed with proper input buffer wired to its input terminal. This would not happen normally, but under some rare circumstances where possibly the classes have hanged when the property node already was placed on the block diagram. Tomi
  4. I know, I just tried to inject new ideas to your endless list of must have features Opening up the property pages to extensions would be enough.
  5. It counts if you are ready to leak the information, more or less privately Seriously AQ, are you considering exposing the <Property Name="xxx" Type="yyy"></Property> tags to the library properties dialog as item and library annotations? I don't want to do duplicate work...
  6. Did anyone have any success on this? I would like to add a page for annotating classes and class items such as methods. LabVIEW scripting provides a way of annotating items but these annotations are not exposed via LabVIEW IDE user interface. I would like to add a page similar to library items settings that would allow adding custom annotations to each item.
  7. I really hope that NI will not localize class property names either as then the child class developers' classes would only work with one localized version of LabVIEW. This would be a nightmare to LabVIEW Tools Network tools developers. Assume there is a class in <vi.lib> that uses localized properties. LabVIEW tool developer creates a tool has a class that inherits from this class in <vi.lib>. The tool is distributed via NI Tools Network. Now someone in Germany downloads that tool with German version of LabVIEW. It will not work, because the localized property names are not matching with the localized version of LabVIEW. The German LabVIEW developer cannot used but German versions of reusable LabVIEW tools. Is this really desired behavior?
  8. Mike, there is a contradiction in what you are saying. You are saying that the long names can be localized, but on the other hand the long names must be the same the whole inheritance hierarchy, i.e. the long name together with the DataName specify the interface of the property to child class developers. Assume I create a class A. I create a property Length with the following names DataName = Dimensions:Length Name = Length LongName = Dimensions:Length ShortName = Dim.Length I publish my class for developers and people in the LabVIEW community create decedent classes of it using these property names. Now I want to localize my class for Finnish market (I am originally from Finland). So I create a localized version of the lvclass file for Finnish market with the following names. DataName = Dimensions:Length Name = Length LongName = Mitat:Pituus ShortName = Mitat.Pituus This should be possible, as you told the Long and Short names can be localized. However, now according to the requirement that the Long Names must always be the same throughout the inheritance hierarchy, the descendant classes created by the community no longer are compatible with this localized class. My interpretation is that localization should never change any interfaces of a class. If long name is required to be the same, then interface is changed. EDIT: Just tested the above mentioned behavior and changing the localized names indeed breaks the inheritance hierarchy of your class. If you are intending to allow third party developers to inherit from a class that you develop, my recommendation is that never use localized names.
  9. I am not quite sure if this is a related bug but I noticed incorrect behavior with property nodes when uses w/o DVRs. Basically the property node breaks for a child class if only one accessor has an override method. I wrote a post on NI forums. http://forums.ni.com/t5/LabVIEW/Class-properties-of-decedent-class-access-scope-error/m-p/1399220#U1399220 Tomi
  10. Thanks Mike, that was a comprehensive answer. Now I assume I know how to change those names in scripting and editing lvclass files. But how do you have an access to all those names in the class editor (LabVIEW project)? Second question is that do the names in an inheritance hierarchy need to be the same or is it enough that the DataName is unique? If there are conflicting definitions for long name and short name, will LabVIEW show an error? I ask this because if I create a class, specify the long and short name for a property, then someone creates a child class for that class and wants to override the property accessors, does he or she need to set the long and short names to be exactly the same or would LabVIEW use those of the parent class that first defined the property? Third question, how do I localize the long name and short name, not likely I am going to do that but just in case I might?
  11. Hi All, Happy Holidays! I am back for more. JKI has been keeping me busy. Property Definition folder LabVIEW project item has properties DataName, LongName and ShortName. When you look at LabVIEW class file, the XML contains all three types of names for a property definition folder as well. However LabVIEW IDE does not expose these names to the user, at least not in a way that I can change anything but one common name. Is there a difference between all these three names? Does LabVIEW differentiate between the names? If not, is this planned for the future? Cheers, Tomi
  12. is excited to have met all @NIWeek

  13. JKI presentations can be found from our blog.
  14. is writing unit tests

  15. I wrote an article on the subject a few years back on ExpressionFlow expressionflow.com/2008/06/02/extending-labview-built-applications-with-lvoop-plugins/ Tomi
  16. Felix, I am sorry we really don't have functional programming at all in LabVIEW. What we have is OOP. The blog post was intended for more general audience of dataflow programming languages than just LabVIEW developers. In functional programming you can pass all functions as a parameter to other functions.
  17. I posted a new article concerning the general concepts behind design pattern that may be clear to many LabVIEW developers but not software engineers of other programming languages. Further I updated the example LabVIEW project with a worker pool that supports recursive worker instance reusage. Please copy paste the link below, direct linking to LAVA is prohibited by a LAVA bug. expressionflow.com/2009/11/10/unlimited-parallelism-concurrency-with-recursive-dataflow Unlimited parallelism & concurrency with recursive dataflow Tomi
  18. I was thinking of an alternate solution, that may be little more complex. Assume you have a sequential worker pool and a parallel worker pool. Sequential worker pool is a loop that dequeues commands and executes them in a sequence. Parallel worker pool on the other hand consists of a single sequential worker pool and a recursive call to parallel worker pool itself. Within the parallel worker pool, the sequential worker pool and parallel worker pool are running in parallel. Neither of these, however listen to the main queue, but a new queue is created for both the parallel worker pool and sequential worker pool instances. In parallel to both of the two worker pools, there is a dispatcher loop. The dispatcher loop listens the main queue. Once it contains elements, it either submits the element to one of the two queues representing the two worker pools, parallel and sequential running in parallel. If the sequential worker pool is busy executing a task, then the dispatcher submits the incoming task to the parallel worker pool. If sequential worker pool is free, then it gets the task.
  19. Now if there is initially a single task in the queue, the outermost workerpool instance starts executing it. The next worker pool exits because of a timeout. Now submitting a next task to worker pool needs to wait for the first task to finish. So it doesn't get executed in parallel with the first task. If the first task is locked waiting for second task to do something prior to proceeding, then the program ends up into a dead-lock. The number of workers in the worker pool for parallel loop is limited by a development time set upper limit. Furthermore the number of workers is fixed at the time when the loop starts executing. Unlike the proposed architecture, you cannot dynamically at runtime increase the number of workers as needed. Therefore it suits to parallelizing a mathematical analysis where tasks may be independent but doesn't suit very well for situations like dynamically adding listeners for a network connection. State machine architecture is indeed something I had in mind when I came up with the worker pool design pattern. To be more precise, an ability to have parallelly executing substates to represent a single outer state. I am not yet ready with my state machine design but I will blog on it once I have solved the problems I am still having.
  20. There is a patch for LV 2009 you should add. Maybe it fixes the problem. If not, then go on trying to debug the issue.
  21. This is exactly the kind of discussion I wanted to raise. I would like the community to get help from the community to develop the best way to use this design idea. Ragglefrock, in your example there is a problem. The recrursive call to the worker pool exits immediately if there are no longer stuff to process. The outer most worker pool exits after it has finished its own task. So that worker pool doesn't wait indefinitely for new commands but exits after it has processed the first command in the queue. Indeed it functions as the dataflow worker pool, executing all the commands that are in the queue when the worker pool is started and then exits.
  22. Hi, I posted a new blog post on worker pool design pattern to expressionflow. Worker pool - a design pattern for palalle task execution in LabVIEW if the link above doesn't work, please copy paste the address below to your browser: expressionflow.com/2009/11/04/worker-pool/ Cheers Tomi
  23. Something similar. We are talking about some technique of creating code acting similar to polymorphic VIs, without the need of duplicating the code. But not only that. We are also talking about custom _polymorphic parametrized types_. An example of a polymorphic type in LabVIEW is array. Array can contain any datatype imaginable and array type includes the information of the array element type. Even though LabVIEW has polymorphic parametrized types such as arrays and queues, developers are currently not allowed to develop new such types. Unlike with C++ templates, with generics the possible runtime types are not known at compile time. Of course the all possible types are known, but that type space is much too large, so a binary code cannot just be generated to all possible types. Generics are not replaced by the exactly typed counterparts at compile time like C++ templates. Instead a generic binary code is generated, or alternatively binary code is generated just-in-time before at execution time. As I mentioned above, a generic binary code for generic functions is generated. So for generic classes there would be a single generic class. For generic VIs there would be a single generic VI with a single binary code. As LabVIEW VIs have a state (controls, uninitialized sift registers), this is the only way to implement generics in LabVIEW I can think of. In LVOOP method VIs with dynamic dispatch input terminals, the method call is bind to actual method VI at runtime. In a similar manner in generic programming, the method calls to primitives or other subVIs are bind at runtime depending on the runtime type of the generic. As the type checking is happening at compile time, there always exists a method or primitive to be called. Runtime type checks can never lead to a situation where the generic code cannot be executed. EDIT: I was checking details of C# implementation of generics. When primitive types like Float and Int are used for type parameter, a separate code is generated at runtime. When class types are used, then code is shared betwen different types. That is List[Float] and List[int] would have their own binary code but List[string] and List[List[Float]] would share the binary code. In all cases, the code is generated at runtime, when first needed.
  24. Err.. I think you misunderstood. Sorry, I need to try to be more clear. I am talking about only static i.e. compile time type systems. Forget dynamic languages for now, I am not referring to dynamic type systems. I don't think dynamic type systems fit to LabVIEW dataflow paradigm very well. In a statically typed language like LabVIEW, type checks are done at compile time. In LabVIEW the type checks are done actually at development time, but it doesn't matter for now. The whole idea of static type checking is to prohibit type mismatch at runtime. This far we both agree. Now generic programming IS NOT the same thing as dynamic type system. Generic programming can be made 100% type safe using type parameters and compile time type checking with a static type system. All type related bugs can be avoided like currently in LabVIEW. The actual type comes into play when you place a VI that uses generic types on a block diagram. When you connect a wire with a specific type to a input that depends on some type parameter T, the type parameter T gets bound to the type you connected. That fixes the type of all inputs and outputs that depend on this particular type parameter. In dynamic programming, the type of the output terminals would be of type Dynamic. With type parameters the type of the output is fixed to something specific instead. As an example, consider a method creating a LIFO (last in, first out) stack of anything. In dynamic programming you would have an input of type Dynamic. The output terminal returning the stack would be of type Dynamic as well. In type parameter based generic programming the input would be of generic type T and the output would be of type Stack[T] (stack of items of type T). When you connect say integer I32 to the input of the create stack method, then the output would become fixed to a type Stack[i32] (stack of items of type I32).
  25. I guess you are referring to the fact that VIs using generic types need to be runnable. That is indeed a good question. What is needed is a default value for generic types used as type parameters. For unrestricted type parameters this should be rather easy; there is no need for any particular value. So unrestricted type parameters would behave the same as LabVIEW Object class. The default value would equal to the top most class in the class hierarchy. The default value of a generic type with a single upper bound can be represented with the default value of the upper bound type itself. The default value of a generic type with a single lower bound can be represented with a default value of the parent class of all other classes, which currently is LabVIEW Object class. The more challenging is the case when multiple upper bounds have been used for a single generic type. The usage of multiple upper bounds from different branches of class hierarchy is possible only if either mixin classes are supported or interfaces are supported (I prefer mixin classes over interfaces), or there is some other kind of support for multiple inheritance. Let's consider the option of mixin classes which would in a LabVIEW implementation have a default value. Let S be any type that inherits from any two classes U1 and U2. For this to be possible, S needs to be a class in type space defined by direct sum of U1 and U2. The same applies for any generic class T that has upper bounds U1 and U2. So the default value of the generic type parameter T that has upper bounds U1 and U2 would be a direct sum of default value of U1 and U2. In less mathematical terms, the default value of T would be a data structure similar to a two element cluster with default value of class U1 and default value of class U2. For more that two upper bounds, this would generalize as a direct sum of upper bounds {Ui}. So far we have assumed upper bounds are non-overlapping. That is for any two upper bounds U1 and U2, there is no class Q in the inheritance hierarchy for which Q is a common ancestor for both U1 and U2. The easiest solution would simply not allow this kind of type bounds and also disallow multiple inheritance from common ancestors trough two different inheritance branches, unless of course this ancestor class is LabVIEW Object or similar built-in class. There are other options as well, but they are not relevant for the discussion now.
×
×
  • Create New...

Important Information

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