Jump to content

bsvingen

Members
  • Posts

    280
  • Joined

  • Last visited

Posts posted by bsvingen

  1. index.php?automodule=downloads&req=display&code=sst&id=25

    File Name: Pointer System

    File Submitter: bsvingen

    File Submitted: 18 Sep 2006

    File Updated: 29 Sep 2006

    File Category: LabVIEW OOP (GOOP)

    Pointer System V1.1.2

    Author:

    bsvingen - Bjornar Svingen

    bjornar.svingen@ktv.no

    Distribution:

    This code was downloaded from:

    http://forums.lavag.org/index.php?automodule=downloads

    Description:

    A set of VIs that creates and controls pointer-data pairs. The basic idea is to simulate random access memory and malloc()/free() by using one single LV2 style global. The data type must specified in "..\Pointer\Data Typedef\Data Typedef__P.vi", or it can be replaced with an LVOOP class for LV 8.2. The only restriction to the number of references is the physical memory on the computer. The global stores data in an Array and uses a separate Bool Array to control access and free/protect the data.

    The "address" to the data is returned directly with no type conversion (int32). Basicly the LV2 global takes data as input, put the data in an array within the global and returns the index where the data is set. This index therefore becomes a pointer to the data, and can be used later to set and get data.

    The upper 8 bits of the pointer is used as a counter that is incremented by one for each new "dispose pointer" call. The "Get" and "Set" function checks these 8 bits in the pointer with corresponding counter array and throws an error if they are not equal. By doing this an error is thrown when trying to use a disposed pointer. Thanks to JFM for the counter code.

    Due to the inherent effectiveness of LV2 style globals and no type conversions, this method is twice as efficient as using queue primitives, see examples provided. Functions such as New, Get, Set etc can be found in the ..\Pointer folder. A project file is also provided for LV 8.x. A more general system that takes arbitrary types is called General Reference System and can be found on this Code repository.

    In contrast to queues that can be regarded as synchronous references to data, this reference system is fully asynchronous.

    Allocation and freeing of data is done dynamically.

    Allthough this pointer system may at first glance have some resemblence to "classic" GOOP, it is by no means a GOOP system. This pointer system is best regarded as a normal LV2 global, but with the difference that it returns a pointer (index) to the data, and therefore can be used for an arbitrary number of data.

    All the VIs in the library are documented.

    Support:

    If you have any problems with this code or want to suggest features:

    http://forums.lavag.org/index.php?showtopic=4131

    Version History:

    1.1.2

    Fixed "dispose pointer" and "obtain pointer from pointer". Some other small fixes.

    1.1.1

    Updated the counter so it will increment at each "dispose pointer" instead of "obtain pointer".

    1.1.0

    Updated the pointers so that the upper 8 bits is uses as a counter. Using a disposed pointer will therefore create an error. Thanks to JFM.

    Updated the allocation routine so 100 elements are added in one chunk. Thanks to JFM.

    1.0.1

    Updated this readme.txt file

    Fixed a bug in "Obtain P from P" function in the global.

    Added a placeholder VI (for easier conversion to LV7)

    1.0.0:

    Initial release of the code.

    License:

    Creative Commons Attribution 2.5 License

    Click here to download this file

  2. Do you have any examples of using this to implement linked lists yet? That and Data Tree structures would seem to be logical uses for your toolkit.

    Thanks for posting!

    I have one example in the other thread here. It is the last one called Pointers Typedef V02.zip and can quiclly be modded to variant type. However, i think a linked list class would be made in a more elegant manner directly into the global using the same technique as the reference global, but with two extra arrays inside used as pointers to "next" and "previous" (for a doubly linked list or binary tree).

  3. To me this looks pretty much as associative Arrays with string as the key. Why not built this mechanism into the ordinary array functions? That is where it belongs. Or parhaps better, make some associative array functions.

    Also, if you use a flattened to string as the key/name, it will in all respect become an associative array that can take anything as the key.

    Maybe a good OpenG Project :question:

    :2cents:

  4. Ah, stateless VIs. I'll add your voice to the chorus. I'd love to have that, too. ;-)

    Don't worry. ;-) This wouldn't affect all VIs. The idea would be a VI that you could explicitly mark as a stateless VI and thus prevents uninit shift registers, local variables, the Value property of controls and requires all controls to be a) connected to the conpane AND b) marked as requiered inputs. VIs that are stateless have some very nice properties that can be used for a variety of situations. Further the code can be optimized a lot.

    Yes, I see now that optimization is one thing. Maybe inlining by the compiler ? :)

  5. Well, whatever you decide doing please don't change anything in LV simply because it does not fit into a puristic idiology of some programming concept and/or have side effects that may be "misused" (whatever that is supposed to mean).

    Shift registers (initialized or not) and LV2 style globals is probably the single most important reason why it is possible to do anything in LV besides passing data linearly down a wire from A to B via function Z(A). In the end it all boils down to getting real world results (on all levels).

  6. I think the marked is (semi) remote logging sending a file every now and then. Even today there are many applications that use mobile phone technology, especially in security (home burglar alarms for instance).

    Anyway, it's not easy to understand business desitions. Palm for instance. I have a Tungsten T3 that I bought 2 years ago. It has everything i need (large screen, very powerfull CPU, lots of ram, bt) but it lacks a phone. Instead of adding a phone into that casing, Palm has chosen to go forward with their Treo smartphones. The problem is that the Treo is no match for Nokia and Sony Ericsson having much better phone technology and more functionality built into them. So no one is considering bying a Treo as a phone because it is a very poor choice compared with other manufacturers of smart phones, and no one is considering bying a Palm PDA because it has no phone.

    Pretty soon, due to lack of a real Palm with a phone, my Palm T3 will be retired as GPS only device and my "old" :D 3G SE phone will be replaced by a SE/Nokia smart phone.

  7. Unfortunately I can't test it right now because I'm uninstalling 8.0 and installing 8.2

    [Edit:]Found it, it is an option in Tools>Options>Envirenment>Use native File dialogs[/edit]

    Ton

    I'm just curious to why you are uninstalling 8.0. The ability to have several LV versions and change between them at will, is probably one of the really strong things about LV. I have 6.1, 7.0, 7.1.1, 8.0.1 and 8.2 on the same PC.

  8. I think this example show all too obvious why dataflow is not exactly rocket science in terms of compiler technology/programming paradigm. In my first larger project i was wondering about the exact same thing. I had one loop for logging and one loop for several PID controllers. The PID loop was run at a much slower rate than the logging, but at a steady rate independent of the logging loop which would change rate according to user specifications. I also ended up with using global variables, even though the manuals also back then said "use globals only when neccesary because they are inefficient and will break the data flow" or something like that + "dataflow make parallell operations easy and fool proof".

    1. You cannot pass data out of a loop without breaking the dataflow.

    2. The only way to run in parallel is to break the dataflow.

    So that dataflow really makes parallel operations easy and straight forward is some big myth IMHO. Dataflow just as often prevent parallel operation where parallel operation are the only natural thing to do. With queues, goop, lcod etc all this is now more or less an academic discussion, except for newecomers to labview, and it is therefore a bit strange that NI still advocated that dataflow is THE big thing for parallel programming.

    :beer: :)

  9. I have updated the pointer system a bit. This version is made for a strict typedef (see project explorer).

    I have also included a linked list that is made with this pointers. A linked list consist of a structure (a cluster) that has one or more pointers that point to other clusters of the same kind. With linked lists one typically can build trees, stacks, hash tables and all kinds of dynamic structures. A linked list is fully dynamic and exist entirely hidden in memory except for the single starting node.

    The funny thing is that when building this linked list with the pointer system, one get a list that fully (as far as i can see) adheres to data flow principles (as can be seen in the BD, although it is only the single starting point that flows).

    Download File:post-4885-1156792100.zip

  10. OK, I have converted my Pointer/ref system to LV2OO. I have not tested it performance-vise because i'm not sure if i have done everything correct yet. My experiences are these:

    It was a somewhat of a pain to make all the classes and all the get/set functions needed for each class, especially when they all are virtually identical. I mean OOP, isn't that about code reuse? It was also a bit painful to stretch my head to think in "LVOOP way" about these actions instead of a simple case statement. Isn't this kind of programming actually called actor oriented (AO) and is more of a functional programming thing, or am i totally lost here??

    When it all was finished i noticed a severe limitation (bug?) of the Project Explorer/inheretence functionality. Every inhereted function(vi) need to have the same name, but since they cannot have the same name in the same folder, i had to make separate folders for each and every inhereted vi. When there is no direct relation between the folders in the Project explorer and the real folders, this is *really* confusing and extremely irritating.

    When that was fixed it worked at first try :D when looking at the code, and the ease of which things now can be changed, add functionality etc, i have to admit that LV2OO is a major leap in the right direction even though the initial amount of code needed at least doubles for this simple pointer class. The downside is that because the code is "granulated" down to its smallest units, it IS more difficult to get an overall picture of what the code actually does (at least it takes more time), but at the same time this granulation makes it much easier to test the code, and therefore make it work at first try.

    All in all, i'm impressed so far. I still don't know how LV2OO scale up to be used for general LCOD style, and i am still a bit concerned about performance, but for normal LV2Globals it certainly is a very radical improvement :thumbup: :thumbup: . I have included the code.

    Download File:post-4885-1156686272.zip

  11. So that would explain the allocation at the tunnel, but why another allocation at the indicator?

    Thats a good question :) Sorry, but i din't see that at first. I think the answer is that the control and indicator have separate memory allocation rules, different from wires and subroutines. The indicator can have different dimension compared to the control, so a separate buffer for the control is set.

    I ALLWAYS make sure that i do not change array dimension in subroutines unless that is part of the functionality. I learned that from trial and error and from boards like this. I think your example show the impotrance of this, although *exactly* what is going on inside the compiler is still a bit mystic to me.

  12. Well, after some more thougts i think that when using LV2 style globals and LCOD programming style the reality is that the LV2 global is not just a storage buffer, the LV2 global(s) *is/are* the program. The reason this works is because you can have an abundance of shift registers for all the different data and operate on them in any thinkable manner according to the LCOD function. Adding and deleting data is just a matter of adding and deleting shift registers.

    With the LV2OO you have to cramp all these data from shift registers into one VI. This will cause at least two problems. Adding data (for instance adding one more array and a few bools that you forgot to start with) becomes a serious task when you have to change maybe several tens of sub classes and their VIs. Another problem is that there just is not enough slots in the connector pane for input and output of data.

    Besides, when thinking of the LV2 global in terms of LCOD style, since the LV2 global is the program, changing that LV2 global WILL be a serious and error prone task no matter how you look at it. But i dont think it will be more complicated than changing the code in a LV2 global than changing the same code in a child class. It will probably? be more work in LV2OO because you potentially also have to change a multitude of connector panes?.

    But i have to try this LV2OO first because it looks very interesting :) . However, i have a feeling that LCOD is such a strong programming style on it's own (completely unbeatable compared with any GOOP when you have lots of data to manage and send around), that a truly strong concept would be to put LVOOP into the frames of LCOD, and not the other way around.

  13. Whenever you change the size of an array, memory need to be allocated/deallocated. Therefore, if the array dim entering the tunnel on one side is different than the dim on the other side, labview creates a buffer. Replace array subset conserve the dim, while build array changes the dim. This has to be so even though the dimension does not really change in your vi, because LV has no way of knowing the the dim in the new data is the same as the dim in the deleted data.

  14. This is very interesting indeed. I have downloaded the code and looked at it. It took mee some minutes to grasp what was going on :D but i *think* i'm starting to understand it. My first impressions are these:

    LV2 style globals are the only way to efficiently store data in LV. Queues can be used, they are very efficient (for small and moderately sized data), they also are inherently syncronous and to make them asynchronous requires some work and the efficiency drops rapidly. However, the main advantage with LV2 style globals (also compared with all of the GOOPs) is that they are the only structure in which large complicated data can be operated on efficiently in an interacting fashion. For instance, you can have several large arrays, and arrays of clusters, and want to operate on them per element basis without unnessesary buffer allocations and copies - LV2 globals are the only programming style that can be used. In addition, you want to read some *some* of the data in the globals at varying frequency in other locations for storing to file, plotting in graphs, sending over internet etc, then reentrant LV2 style globals called by ref is unbeatable (i usually use queues to send the references at init to werever they are needed). The price for all this, is that making changes to a large and complicated global is a difficult and very error prone task, where it is very easy to add bugs allso to code that previously worked well. To simplify this will be a huge step forward.

    I'm a bit concerned about efficiency of the LV2OO. I will try to have something up and going an compare it with a normal LV2 global (and dqGOOP :) )

    Another thing is that LV2 globals are very straight forward, and therefore easy to use and understand. The LV2OO looked esoteric in comparison, but maybe i just need to get used to dynamic dispatching and stuff and it becomes less esoteric.

    :thumbup:

  15. Well, it doesn't seem like this is of outmost interest for many people here :D , but i think i'm converging towards something useful. I have done some changes to the core LV2 Global. It is dynamic, but there are also minor internal changes that, in some strange way probably due to some LV memory handling/buffer allocations ??, improves performance quite a lot.

    I have also made the LVOOP different so that it takes Variants as input. I have renamed it to Pointer Class, because i think that is a better description, and i have added some pointer aritmetics (can be used for very cool, but buggy? code). When using LVOOP for the pointer, and Variants for the data, the performance increases even more. A simple by ref GOOP made from this pointer class is almost twice as fast as dqGOOP in get/set, and up to 16 times faster than the locked dqQOOP class (get).

    So, im converging toward the pointer class. It is fastest, it makes pointers/references to *anything* including LVOOP Objects, It is much more secure, because the LV2 Global is protected (only member functions can call the global) and the pointers/reference - wires can only be used by the member functions. It is also more elegant than the others IMO.

    Download File:post-4885-1156527660.zipDownload File:post-4885-1156527684.zip

×
×
  • Create New...

Important Information

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