LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
Blokk

New Message Channel wire type with option to specify destination

Status: New

I find the new Channel wires very useful things! However, I really miss one type/variation which would make a real many-to-many lossless message sending possible, but also with total control over where the msgs end up in case of multiple readers! Imagine that we have a Channel wire which can be branched, and you can also specify a "destination label" (could be a number, or string, etc.) at the Write nodes. This new Channel type would allow multiple Write and Read nodes. At the Read nodes, we could also specify the "destination label", so ONLY those Reader nodes would get the actual message which are subscribed for that particular "label".

 

I can program this functionality, but it would be great to have such features in a single Channel wire...

What do you think? Is this a good idea or you see some caveats/downsides of such Channel?

9 Comments
Blokk
Trusted Enthusiast
AristosQueue (NI)
NI Employee (retired)

This is a bad idea and a good idea, all in one! 🙂

 

Short version: We have considered doing something like this because it would address one particular problem, but we have resisted doing it because it isn't a good solution (see below for details) so we keep holding out for something better. But nothing better has been forthcoming. So... maybe despite being a bad idea it is nonetheless the best idea? Maybe.

 

Long version: If you have multiple receivers, I would generally suggest you should create multiple messenger channels, one for each receiver. Your runtime performance will be better than any sort of routing protocol AND it will be obvious on the diagram who is talking to whom. That's kind of the point of channel wires -- step away from the paradigm of "fire this off into the ether with no graphical awareness of who is catching it" and step toward "draw the explicit connections so you can trace where every message goes."

 

Having said that, I am aware that the pattern of "N senders all send to a single receiver, which serially processes requests and then sends the results back to the original sender" is not easily modeled using channel wires as they stand today. Let's call that the "central processing pattern." The "routing protocol messenger" idea would address that need.

 

Currently, if you're going to code a central processing pattern, you need to encode in your sent messages an value representing the original request-maker (enums work well here). After your central receiver processes a request, it uses a case structure on that enum to pick one of N channels to send back to. Every origin point has a separate enum value and a separate channel.

 

Clearly, that's a pain in the neck to write. But it  is quite delightful to debug!

The pros:

You can breakpoint specific frames easily; you can monitor all the traffic to one of the request-makers; the graphical connections and intention of the channels is clear when studying the code; you don't have the performance overhead of routing protocols.

The cons:

You can quickly exhaust the conpane of your central receiver if you have many origin points; you have to uniquely identify each of the senders (error prone coding process); adding another request-maker is multi-step process; you come away from the whole process thinking, "Surely there must be a better way."

 

As I said, your routing-protocol messenger idea would fill this hole. But when we have modeled it, it isn't fulfilling the goals of channel wires in G... and we in R&D come away thinking, "Surely there must be a better way." 🙂

 

We have never actually built that channel. Maybe it isn't as bad as it looks on paper. If you really think it is a good idea, believe it or not, you can build it yourself. Creating new channel protocols is not something we advertise (because the process is pretty wonky), but it can be done entirely in G code. If you want to try it, here's how you get started:

  1. Open "resource\Channels\Messenger\Messenger.lvlib"
  2. Do Save As>>Copy Entire Library to "resource\Channels\MyMessenger\MyMessenger.lvlib". This will duplicate the entire messenger library.
  3. On disk, manually copy "resource\Channels\Messenger\Messenger_DialogHelp.vi" to "resource\Channels\MyMessenger\MyMessenger_DialogHelp.vi"

Now you can start editing your new template.

You may encounter some oddities... Messenger is the hardest of the channels to manipulate (if you were asking for a new kind of Stream or Tag, this stuff is dead easy). You can post questions in http://ni.com/channelwires to get help.

 

I realize you may not want to code this yourself -- you may not even have time for this kind of experimentation. I'm just flagging it as possible, and if you do it, please post to that ni.com forum with your results and feedback.

 

If anyone has ideas on a better solution to the selective-multicast-with-channel-wires problem, we are open to hearing them.

Blokk
Trusted Enthusiast

AristosQueue: you bring up very valid points, I learnt some new stuff today. Also, your reply put these things into a new perspective for me. I need some time to think about it, I might reply back at a later point. 

Thanks for your feedback!

 

Edit: as a not 100% alternative, would it be possible to create a lossless Tag Channel? So all Readers would get the same msg from any Writer...

AristosQueue (NI)
NI Employee (retired)

Lossless Tag would be tricky... how would the channel know how many endpoints to wait for? Any given endpoint might quit out and leave the others running. That was a problem I faced with the Event Messenger.

 

Tangent: I just realized that if you're going to write your own Messenger, start with Event Messenger might be easier ... it dodges some of the complexity of Messenger since it doesn't have to deal with message filtering.

 

I think the way you would have to do it is with one Tag channel and N acknowledgement channels (say, 1-element streams) -- the writer loop would write to the Tag and then read from ALL of the acknowledgement channels with infinite timeout, and only after those committed would it proceed (you could move the reading of the acknowledgement to be just before the next write for performance improvement). That way you'd be coding in how many acknowledgements to listen for as a static declaration. And if any reader quit, that reader's acknowledgement channel would just return done=true so you wouldn't hang on it.

AristosQueue (NI)
NI Employee (retired)

I went and asked the Skyline team about lossless tag. Lead developer on that project didn't know of any implementation of lossless tag that wouldn't require some kind of communications back channel, so if we're sticking with the "make it explicitly graphical" philosophy of the channel wires, what I suggested above with the acknowledgement channels is probably in the right direction. YMMV.

Bob_Schor
Knight of NI

I think it is a bad idea.  One cornerstone of the Messenger Channel is that while in the Channel, "Messages are neither Created Nor Destroyed".  I posted a reply to the Forum Post that I think got Blokk thinking about this where I had the fun of creating a VI whose explanation legitimately contained the phrase "Train leaving on Track 3 for Anaheim, Azusa, and Cuc...amonga".  It has an explicit "Dispatcher" routine that sends Messengers to their "appropriate" Reader, without any branching.  I also discussed in this thread using a Messenger Channel with multiple readers to handle "Divide into parallel tasks and conquer" algorithms.

Blokk
Trusted Enthusiast

Yes. I started to "shift" too, and now I start to feel that this idea a kind of "not really needed", it would not give me more than I can already gain using Dynamic User Event communication.

Let me first explain a common usage case I like to implement in my recent projects. I have the feeling that transforming my Event comm into (Channel) Event Messenger would not do too much difference. AristosQueue suggested above also this, and this is what I use, but not in the Channel form, but in the "old form". Anyway, let me show you what I talk about, and you might suggest how this could be improved using the Channel "version" of Events?

 

So one common usage case when I have a central communication place which is my Main.vi. Here I have a single Event Structure which takes care of the GUI interactions, but also registered for a certain User Event. In the example below, I use 5 different User Events, and I bundle them up with the help of a Typdef cluster, and I store these User Event Refnums in a FGV.

 

In my parallel modules (either living in the BD, or just called dynamically and displayed for example inside of a SubPanel) I use kind of State Machines with one case having an Event Structure inside. These Event Structures are exclusively for capturing User Events, and each module registers for one or multiple User Events as required. Also, because I can access any User Event Refnum via the FGV, I can fire anywhere (either in the main.vi, or in any module) the "Generate User Event", thus I have two way communication between the main.vi and the modules, or even between the modules, all depends on who registered for which User Event.

 

Now my question is that, would I gain anything to shift the above scheme to Messenger Event Channels? I do not think, because the point here is to use an FGV, so I minimize the number of wires in my main.vi.

Or should I store the individual Event Messenger Channels inside the FGV...? 🙂

Yes, (channel) wires can help to visualize what is going on, but User Event registration happens at single places only in all modules, so I think this is a good compromise to use FGV to have global access to these (and recently I have a single "set" version of the FGV, at the startup part of the main.vi, so no danger of that some module wants to access a Refnum which does not "live yet").

 

Simplified parts, only picked for demonstration (main.vi example, and some module VIs "live" in the main.vi BD):

 

edit: there you can also see some Tag Channels which takes measurement data from the modules, and send them to the Display loop, I really like these simple use cases of Channels! 🙂

 

UserEvents_comm1.pngUserEvents_modules.png

Blokk
Trusted Enthusiast

During experimentation I just realized something. We cannot "put" Channel wire controls inside a Typdef cluster, thus I cannot copy the same logic as above using an FGV.

However, I could bundle the channel wires up I guess?

Edit: no, it is not possible to bundle Channels. So I think just better to stay with my recent implementation of User Event comm.

However, Channels are still very useful to simplify code at many places in my project! Streams and Tags I use very often nowadays...

Bob_Schor
Knight of NI

Blokk,

     I (now) completely agree with your most recent posts.  There are some things that I think Channel Wires (and, in particular, Messenger Channels) are most appropriate, but other situations (such as the ones you just outlined) where some of the more "traditional" methods, including User Events, are simpler and easier to understand and maintain.

 

Bob Schor