Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/19/2011 in all areas

  1. "Unfair" to a teenager (and really to anyone) means: "Not how I believe it SHOULD be" or "...how I want it to be". You say to him: It sounds like you think not getting what you want is unfair. Does that apply to everyone or just you?
    2 points
  2. Hello Everyone I've been following this thread intently and comparing the comments to a framework that Rob Humfeld, and his team at JET and I have been working on since the CLA summit. Rob presented an idea that he and his team were working on called the JAMA framework. I was able to video record the presentation and the next week when I got the code from Rob I dove in and began working with it. Since then we have made many refinements and used classes to make the framework more powerful. Since this thread has discussed many of the issues that we have tried to design into the framework I thought this would be a good time to introduce it in its current version. At the CLA summit someone said that this framework was akin to an observer pattern. Since I wouldn’t know an observer pattern from a quilt pattern I will leave it up to others to decide what it is. I currently call it the Msg_Routing framework the fully tested version will come from JET sometime later this year. The framework has 4 major components Modules, Msgs, Couriers and Routers. There is a 5th component called Module Router but it is not necessary to use the framework 1. Modules are any vi that needs to sent and/or receive Msgs. To work within the framework the Module will need to create and manage a Courier and a Router for each Msg</li><li><font face="Calibri">2. </font>Msgs is a defined data set that is transferred from one Module to another. All child Msg class will inherit from the parent Msg class.</li><li><font face="Calibri">3. </font>Couriers: An abstract class which is the Msg transfer mechanism by which the Module will receive messages. A Module will create a courier child class and register the class to receive Msgs. Child classes Queue_Couriers,Event_Couriers, and Notify_Couriers are already a part of the framework</li><li><font face="Calibri">4. </font>Routers: These hold the information that tell a shipping Module how to get it’s Msg to other Modules. A Router is created for each Msg and they share the same name. A Router is a named single element queue so all Modules can access the same routing data. The Router’s data is an array of Couriers.</li></ul><br><br>Framework features<br><br>Modules are totally autonomous and can connect and disconnect from the framework at run time without affecting other Modules. The Module is responsible for connecting and disconnecting to and from the framework and is not dependent on its caller for anything. Modules have no knowledge of each other only the Msgs they deal with.<br><br>Modules are responsible for creating and destroying their own Msg transfer mechanism called Couriers. One of the attributes that I have use from the Actor framework is that a Module is responsible for creating and destroying its Msg Courier. Callers no longer have to create a reference and pass it to the callee. <br><br>Msgs are Global in scope and are usable by all Modules. Any Module is allowed to ship or receive a defined Msg. Msgs and Routers are the only two things that connect Modules to each other making this framework very loosely coupled. <br><br>The Msg transfer mechanism or Couriers is abstracted. This allows one modules to use "Events" to receive Msgs and another to use "Queues". The decision to use Queues, Events, Notifies, or any other is made on a Module by Module decision and does not have to be a system wide constraint. <br><br>A Module must register for every message that it wishes to receive. To receive a Msg a Module must find the Router and place it’s Courier in the routers shipping array. <br><br>To send a Msg a Module gets the Routers shipping array for the target Msg and ships the Msg to each Module via its Courier. Data consistencyis maintained because Msgs are copied and sent to Modules not stored. <br><br>Here are some diagrams to help visualize the framework. They correspond to the demos in the attached code.<br><br> <br><br><br><br><br><br><br><br><br><br><br>Developers<br><br>Module Developers only need to care about few things to work within the framework. What messages to receive, how those messages will be received and what messages to send. Developers can choose which method of Msg transfer works best for the module requirements by using a Courier child class that implements a specific mechanism. Only the Msg format is defined by the frame work how those Msgs are sent is up to the developer.<br><br> <br><br>Major Points<br><br>Msg transfer is completed without any kind of mediator loop.The Msg Router provides the information on how to send the Msg and the Module Shipping the Msg does the actual work.<br><br>Because it is the shipping Module that does the shipping and not another mediator loop, there is little loss in performance. <br><br>Modules are only coupled by Msgs and not the way in which they are transferred.<br><br>The full framework is attached complete with code, demos and images. It is written in LV 2010. <br><br>To start using the framework load the project and open the [Module Tree].vi all of the instructions are in the block diagram.The diagrams and instructions are inside the cases of the case structure.<br><br>Please let me know what you think of the framework good, bad or otherwise.<br><br> MSG_ROUTING.zip<br><br>Mark
    1 point
  3. Looks like they just released the scheduler. Here's the direct link: https://sine.ni.com/...tmp2=niweek2011 Here's the link to the community discussion in case the direct link doesn't work for you: https://decibel.ni.com/content/message/24924#24924
    1 point
  4. I had issues using notifyicon on XP - I couldn't get it to work.
    1 point
  5. I can't claim it's common, but here's what I do: For development, my applications are designed as components, each component consisting of one or more libraries (.lvlib), and each library containing one or more classes. Each class has a unique file system directory that matches the name of the class. I put the .lvclass file and all methods in this directory. Since each class member must have a different name and I work through the project explorer window instead of the file system, I don't bother creating subdirectory to group class methods. It creates too much maintenance during development. I group them using virtual folders in the project explorer. I do the same thing with libraries. Each library gets its own directory of the same name. All classes that are members of the library go in the library directory. My directory trees often look like this: ProjA\ProjA.lvproj ProjA\src\MyLib\MyLib.lvlib ProjA\src\MyLib\ClassA\ClassA.lvclass ProjA\src\MyLib\ClassA\Method1.vi ProjA\src\MyLib\ClassA\Method2.vi ProjA\src\MyLib\ClassB\ClassB.lvclass ProjA\src\MyLib\ClassB\Method1.vi ProjA\src\MyOtherLib\ClassA\ClassA.lvclass etc. For distribution I just copy the library's directory, assuming it doesn't have any external dependencies.
    1 point
  6. I disagree - (yes, llb's are old) but I like to distribute a single class (or library) as an llb. Of course, multiple classes (or libraries) would mean multiple llb's for that distribution.
    1 point
  7. When a class is loaded into memory all methods are loaded into memory as well. .llb files are old technology and don't work well for distributing classes. Packed project libraries *may* be an option, but there are lots of gotchas and you need to be careful. There isn't really a LVOOP-compatible equivalent of llb files yet.
    1 point
  8. I talked to Rob... I pointed out that he is the father of the JAMA architecture, and I asked permission, and he said, yes, we can therefore refer to him as "Pa JAMA".
    1 point
  9. Orange nodes are configured to run in the UI thread, yellow ones run in any thread. For IsUserAnAdmin() I don't think it should make a difference, but many other Win32 API calls must actually be called via the UI thread (specifically ones which are not marked as thread safe). Come to think of it the documentation for IsUserAnAdmin doesn't comment on thread safety, so it should probably be forced into the UI thread. I'm not sure why you're supplying an initial value to the return variable? Does LabVIEW even let you do that (it shouldn't). Also noted this gem in the docs: Darn.
    1 point
  10. The list should always be sorted. I have filed CAR 308287 to update the documentation accordingly.
    1 point
  11. I tell my daughter fair to who. What she perceives as unfair to her is fair to me... Of course this line of reasoning doesn't work on a tired 3.5 year old when she wants to play barbies and doesn't want to go to bed. By the way does anyone know how to play Barbies? My daughter doesn't want to teach me... I don't think this is fair.
    1 point
  12. I don't know anything factual about the internals of labview, which is lucky for you, because if I did, I wouldn't be allowed to post this. So anyway, it's highly likely that the LV compiler generates executable clumps of code, and that each execution thread in labview is some array or FIFO queue of these clumps. The execution engine probably does a round-robin sequencing of each thread queue and executes the next clump in line. So when a clump contains a Dequeue Element function, and the data queue is empty, this clump's thread is flagged for a wait or more likely removed from some master list of active threads. Then some identifier for that thread or that clump is put in the data queue's control data structure (whatever private data LV uses to manage a queue). That part is surely true since Get Queue Status will tell you the number of "pending remove" instances which are waiting. In the meantime, that thread is removed from the list of threads allowed to execute and the engine goes off and keeps working on the other threads which are unblocked. There's no need to poll that blocked thread, because it's easier to just keep a list of unblocked threads and work on those. When data is finally enqueued, the queue manager takes the list of blocked threads and clears their flag or adds them back to the list of threads allowed to execute. No interrupts, no polling. Of course if all threads are blocked, the processor has to waste electricity somehow, so it might do some NOOP instructions (forgetting about all the other OS shenanigans going on), but you can't really call that polling the queue's thread. It's really cool that the implementation of a dataflow language can be done without a lot of polling. For the system clock/timer, that's surely a hardware interrupt, so that's code executed whenever some motherboard trace sees a rising edge, and the OS passes that to LV and then something very similar to the above happens. So that's not really polled either. OK, I had to answer this out of order, since it follows from the previous fiction I wrote above. Between each clump of code in a thread, there should be a data clump/cluster/list that contains the output wire-data from one clump to be used as the input wire-data of the next one. That's the low-level embodiment of the wire, and whether any C++ pointers were harmed in the making of it is not relevant. Now if the code clump starts off with a Dequeue function, it gets that data not from the dataflow data clump, but rather from the queue's control data structure off in the heap somewhere. It's from a global memory store, and anyone with that queue refnum can see a copy of it, rather than from the dataflow, which is private to the adjacent code clumps in the thread. Well anyway, they do undoubtedly use some pointers here so that memory doesn't have to be copied from data clump to data clump. But those pointers are still private to that thread and point to memory that is not visible to any clump that doesn't have a simple dataflow connection. I think your mental model of how the internals might work is actually getting in the way here. Yes Virginia, there *is* a wire construct in the execution environment. I grant that my mental model could be wrong too (AQ is probably ROTFLHAO at this point), but hopefully you can see why I think real dataflow is as simple as it looks on a diagram. Well we're not getting any closer on this. I still think that other stuff is not pure dataflow, and 'dataflow' is a very useful word. If you say that every iota of LabVIEW is dataflow, then the only place that word is useful is in the marketing literature, and I'm not willing to cede it to them. Maybe the key is adding a modifier, like 'pure', 'simple', or 'explicit' dataflow. Hey I'm learning too, and by the way I really want to try out the Lapdog stuff. I may come back to you for help on that.
    1 point
  13. I agree you could make LabVIEW "more dataflow" by changing the semantics of the language; that is, by changing the rule that a node with multiple outputs releases them all at the same time. However, i don't see it as being useful. So many of the advanced programming techniques like the queued message handler, notifiers, the event structure, and even the lowly global variable are useful in LabVIEW because they violate dataflow. If you could do it all with dataflow, you wouldn't have to fiddle with those advanced techniques. The dataflow paradigm is really great for LabVIEW, but in its pure state it doesn't really get the job done. I don't think any more purity would help.
    1 point
×
×
  • Create New...

Important Information

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