Jump to content

MessagePump: A Messaging Framework Class


Recommended Posts

I've created a framework class which I've used a few times, and tweaked it enough that I think it might be reasonably stable. It's a simple message pump/loop class. It essentially implements the consumer half of what LabVIEW calls a Producer/Consumer Design Pattern, but it can fit into several frameworks when you think about it.

At it's most basic usage, you define a child class with some arbitrary private data, then override ProcessMessage.vi to operate on that data in response to messages. Messages are strings, and parameters are passed to (and returned from) the loop as an Object. This means that you'll likely have supporting data classes defined that allow you to pass relevant data to and from your message handling loop.

Attached are two files:

Contains only the class files.

571de1713ee8b_Capturadepantalla2016-04-2 Contains the class files, and a project that has 3 examples to get you going on what the class does and how to use it.

Some thoughts:

I'm not sure the reentrancy of some of the VIs is the right thing to do. The MainLoop has to be, since it must be able to exist in multiple places if more than one version is running. Similarly, GetMessage has to be reentrant since it's the VI that the loop blocks on when the queue is empty, every running loop needs it's own copy of this VI. The other VIs, I'm not convinced that reentrancy is needed (ProcessMessage, InvokeCallback, Idle, HandleError). I'm leaning to yes for reasons I won't get into here, but I'll see what any of you have to say, if anything.

I also flipflopped a few times on how to handle parameters. Objects are still "messy" in my opinion in LabVIEW, mostly owing to the fact that native data types don't inherit from Object. So even for simple parameters, you're forced to define very simple classes, which I often call "Static Data Classes" since they're often just wrappers around a single native LabVIEW type. Using a variant might be simpler, but I figured since this is an OOP based approach to a messaging framework, it's probably more elegant to keep it all object based. Every time I write another "static data class" though, I curse this decision, there's even a few of them in the examples, see the Int32 class...take a wild guess as to what it does.

I still haven't checked the overhead involved in SendMessage.vi, where a notifier is created and destroyed with each call. But I can't seem to think of an elegant way of re-using a notifier where a previous value won't run the risk of triggering a race condition.

I'd really like to use an Enum for a message, but again, LabVIEW types not inheriting from Object kills that idea. I thought of using my own class that I define, but that just gets messy when using the pump VIs on the block diagram since there's no native way to deal with class constants.

-Michael

Link to comment

Nicely done!

I like the encapsulation above all. It's a simple framework to use on the top-level.

I also really like the idea of passing unknown messages onto the parent class. This is an interesting implementation for handling messages. You could probably architect it another way that wouldn't involve requiring each Message Handler override to call the parent method in a default case, but right now I can't think of exactly how to do that.

Other areas to explore might be to allow different types of callbacks such as user events, which are useful for code that already has an event structure set up. Perhaps there's a way to dynamic dispatch this functionality.

Link to comment

QUOTE (ragglefrock @ Feb 19 2009, 12:05 AM)

Other areas to explore might be to allow different types of callbacks such as user events, which are useful for code that already has an event structure set up. Perhaps there's a way to dynamic dispatch this functionality.

Great idea. Initially I was using events as a callback since the first few implementations went along side event-based producer loops, but I realized the necessity for a whole loop construct might be limiting the use of the class. However, your idea of supporting multiple callback types via a dispatch really intrigues me...I'll have to do some exploration and see what comes out.

Thanks for the feedback!

-m

Link to comment

Well, I really liked your idea, ragglefrock, and it turned out working it onto the framework proved simple enough.

Attached is an updated 8.6 file:

And a legacy 8.5 file:

The OpenG Error Tools dependency is still there.

There's still no example dealing with callbacks, but as before MessagePump::SendMessage.vi still wraps a callback up if you want to take a look. Basically callbacks have been abstracted into a base class called...get ready for it....Callback. Crazy I know. The class defines a dynamic method DoCallback.vi, which is called by the framework after every message has been processed, and by default does nothing. Derive the class though and implement the method and voilĂ ! Instant signaling of whatever synchronization routine you wish. I threw in three classes encapsulating notifiers, user events, and even one for a VI call, but nothing's stopping a user from creating others.

All in all, I think I like this change, it hasn't added much complexity, but has definitely enhanced the utility of the class.

By the way, is it normal I can't edit the original post to update the zip files for download?

-m

Link to comment
  • 1 month later...

Updated again.

Download File:post-11742-1238072753.zip

The OpenG Error tool dependency still exists. The class now handles initialization automatically, though the methods are still exposed through the public interface in case a child class needs to have it done manually. Examples have been updated to show this change. The stop mechanism has also changed to allow the signaling thread to optionally retrieve the data context of the consumer loop.

This is mainly an update to demonstrate an undesired behavior (possible bug) which I'll post about in another thread.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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