Jump to content
drjdpowell

[LVTN] Messenger Library

Recommended Posts

Hi James,

I tried your probe anyway - unfortunately it causes a deployment error (see image). Without investigating, I'm guessing there's something in there not compatible with RT?

I already log the 'states' to a log file, which is how I know if the appropriate states are being fired in each actor. Plus I log all errors to a separate log file.

Trying your ideas:
1) Already made that change, just in case
2) Double checked wiring - it's fine.

So I took a look at "vi.lib\drjdpowell\Messenging\ObserverRegister\ObsReg Core\ObsReg to Table.vi” which shows how to take an ObsReg Core class and represent it's data in tabular form. How can I use this to investigate the number of Observers on the subactor notifier before I send the reply? I presume this is the motive?

Deployment errors when using probes:

deployment_error.JPG

This is how I record the states to file:

log_state.JPG

Edited by Thoric

Share this post


Link to post
Share on other sites

OK, so I think I worked it out. I recover the DVR and run ObsReg to Table.vi and export to file. Unfortunately, introducing this diagnosis code caused the problem to vanish. With this code in place, the issue does not occur. Out of interest, the resultant table contains:

All State	ObserverSet; 
  0: EventMessenger (0x79B00000)	
All Events	ObserverSet; 
  0: EventMessenger (0x79B00000)	
All Errors	--	

We have one Event Observer established. Hence the message was received and no problem occurred.

For sanity I removed the diagnostic code and recompiled it, and the problem is still gone. Aargh! I haven't changed a single other thing! What's going on!?

review_observers.JPG

Share this post


Link to post
Share on other sites

And the problem has returned. No changes. This has to be a race condition. Sadly I no longer have the diagnostic code in there so I have no way to see if the Register had any Observers. I'll reintroduce the code and do some repeat testing (multiple reboots of CompactRIO).

Update:

I can no longer get it to fail. With or without the code segment above looking at the register, it now always works. And I've literally changed nothing else.

...I wonder if a career shift into crop farming would prove less stressful...

Edited by Thoric

Share this post


Link to post
Share on other sites

i don't think there can possibly be a race condition in the code itself.   If you send message A then B, then they are handled A then B.   Could there be a compiler bug on RT affecting either User Events or the DVR the ObsReg uses?

Share this post


Link to post
Share on other sites

i have a frame work that launches actors from and controller actor but with the latest version this ability is broken. after a lot of snooping i found the 'Get Dynamic Launch Shell Reference' was changed. I downgraded the messenger library to the previous version and everything is fine

 

dynamic launch new.png

dynamic launch old.png

Share this post


Link to post
Share on other sites

This is issue 9: 

https://bitbucket.org/drjdpowell/messenging/issues/9/non-reentrant-actors-started-by-themselves#

You can freely change the strictness of the reference to “Dynamic Launch Shell” if you like; so you don’t have to downgrade to an older Messenger Library version.

Edited by drjdpowell

Share this post


Link to post
Share on other sites

Hello James, I am not completely sure, if this crash really is related to the send.vi of your framework (version 1.9.6.99). Have you ever encountered such a LV crash? The crash occurs after a day of runtime (dev template based), where messages are frequently send to the same actor.

error.JPG

Share this post


Link to post
Share on other sites

I not aware of such an issue caused by Messenger Library, and that subVI does nothing other than fire a User Event.   Are you able to make an EXE and try that?

Share this post


Link to post
Share on other sites

Hello James, I tried to reproduce the error, but after a restart of the pc the error seems not to be occuring any more. Thanks for the answer and sorry for the beginner error not to test if restart would solve to problem. 

Share this post


Link to post
Share on other sites

Hi James,

I'm attempting to register two actors in my top level.vi. I've done this before in past projects, but for some reason following the same template I'm getting the following error:

Error 1 occurred at SendMSG.lvlib:Messenger.lvclass:Send.vi:2280001

Possible reason(s):

Attempt to send message to a virtual (non-valid) messenger.

Message label: "RegisterByLabel"

Not sure where to go from here... Any Ideas?

Error.png

Register.png

Share this post


Link to post
Share on other sites

That error is from when one tries to Send a message to the parent class of all Messengers.   The parent class is "virtual" meaning it is an error to actually try and use it, rather than a "concrete" child class like your EventMessenger (orange wire in the image).   Your Aerotech.lvclass "actor" has a Messenger inside it.   If you have never "Launched" it, then it will not contain a concrete child-class Messenger and will throw that error (note: it will throw a different error if it Launched and then Shutdown for some reason).

So, I think you have a bug somewhere upstream that has caused you to "drop" the address of your Aerotech actor, or to never launch it, and you are trying to send to a never-launched actor address.

I will try and improve that error message to mention unlaunched actors.

Share this post


Link to post
Share on other sites

James,

The Aerotech Actor is launched to a subpanel in the previous init steps, the actor is running in the subpanel. What sort of bug would cause the address to be dropped. How would I discover this bug, or better yet how would I go about fixing the problem? Should I re-write the Aerotech actor? Or do you think the problem may be in my Top Level Actor?

Thanks,

Bob

Share this post


Link to post
Share on other sites

My first suspicion would be you forgot to wire the newly-launched actor to your cluster (ie. you "dropped" or "lost" the address). The problem is almost certainly in your Top-Level actor.

Use Probes to debug your actor's address wire backwards.  Using the standard probe, an unlaunched actor address look like this (note the Messenger.lvclass):

Unlaunched Actor Probe.png

While a launched actor looks like this (note the EventMessenger substituted for Messenger.lvclass):

Launched Actor Probe.png

You can also use the custom "Address Probe", which looks like this:

Address Probe on invalid address.png

The "X" indicates an invalid address, though note that this could be a launched-then-shutdown actor address, rather than an unlaunched one.

Share this post


Link to post
Share on other sites

James,

You are absolutely right, I did drop the address. For some crazy reason I didn't think I needed to return the newly launched actors wire to the cluster... Costly mistake.

Thank you so much for your help.

Bob

Share this post


Link to post
Share on other sites

On various occasions I run into the problem where one of my Actors is broken and I didn't realize it (such as a Type Def needs updating, or maybe I accidentally left an Actor in an unfinished state, etc.).  This causes all Actors to not be able to be dynamically launched until the bad/broken Actor is fixed. Since the Actor is dynamically launched, I don't realize this until I try running the program.

 

Is there a good way to figure out which Actor is broken besides going through the process of opening all Actors to find out? 

 

Thanks,

Bruce

 

Share this post


Link to post
Share on other sites
13 hours ago, bmoyer said:

Is there a good way to figure out which Actor is broken besides going through the process of opening all Actors to find out? 

I use the ctrl-L shortcut key to bring up the Error List Window.  Broken actor will have a red X.

Broken Actor.png

  • Like 1

Share this post


Link to post
Share on other sites

Wow, so easy!  I guess when the top-level level VI isn't broken I forget that there's another way to bring up the error window beside clicking the broken arrow!

 

Thanks for all of your help!

Bruce

Share this post


Link to post
Share on other sites

Hi James, I was looking through the VIs and tried searching for an answer, but I can't seem to get my head around how nested actors get triggered to shutdown when their calling actor shuts down. I saw somewhere mention of a queue references whose sole purpose was to indicate to the nested actor if the calling actor is alive, but I cannot figure out how that is implemented in the code. I understand such info is not necessary for usage of the library, but I am curious. Could you please highlight the implementation of this feature?

Share this post


Link to post
Share on other sites

It's an asynchronous action called "Reference Monitor", a variant of the "Address Watchdog" available on the library pallets.   It's started inside "Startup type 2.vi".   That VI exchanges messages with "Startup Handshaking.vi" (inside "Launch Actor") in order to get a Queue created in the Caller for the Reference Monitor to monitor.   The Monitor is configured to send a shutdown message if the Queue dies.

 

Startup type 2.vi Block Diagram.png

 

BTW, this is one of the best examples of "internal complexity to support external simplicity" in Messenger Library.  Having things created by a Caller automatically clean themselves up is a major simplification, but to get this requires sophisticated internal plumbing.

 

Share this post


Link to post
Share on other sites

Holy crap you weren't kidding! That is one deep rabbit hole. I'm amazed at the internal complexity of this library. I guess you really did earn that Dr. title! Very clever solution with the asnyc call to spin-up the reference checker. Is there any reason for choosing a queue vs some other type of reference?

Edited by Conner P.
add a few words

Share this post


Link to post
Share on other sites

I needed a reference I can wait on, and I do not know of a lower-overhead option than a queue.

Share this post


Link to post
Share on other sites

Hi James, how would you recommend making a message class for a specific data type? As a little preview I am trying to make a thread pool class which includes a manager actor and worker actor clones. Normally I would find the variant solution satisfactory, but as we discussed in my post on the NI forum, I have a high throughput application and don't want to give up speed I don't have to.

My initial thought was to just make a subclass of MSG.lvclass like variantMSG.lvclass (sorry if the names aren't 100%, don't have LV with me atm), but then I discovered that the internal send and extract variant message methods DO have "abstract" parent versions within MSG.lvclass. I didn't want to go fussing with the library base classes, so instead I designed the send and extract methods of my customMSG.lvclass to accept a generic MSG object and then internally cast it to my custom child class, allowing the internal methods to do the extracting or writing.

Is this a reasonable approach?

Share this post


Link to post
Share on other sites

I, personally, rare!y make custom message subclasses, though it is my intention that one can use Messenger Library that way.  Somewhere on LAVA is an example I made of doing AF-style Command-Pattern messages.  But I generally either use variants or I create non-message object classes that I pass in messages (example: a dataset object, or job object, or fast-growing object).  The later have useful lifetimes longer than one message pass.

I'm not sure variants are that slow, btw, so I would benchmark before avoiding them.

Edit> "fast-growing object" is some strange auto-spell correction, but I can't for the life of me tell what I was meaning to write!

Edited by drjdpowell
Weird autospell correction

Share this post


Link to post
Share on other sites
7 hours ago, drjdpowell said:

I, personally, rare!y make custom message subclasses, though it is my intention that one can use Messenger Library that way.  Somewhere on LAVA is an example I made of doing AF-style Command-Pattern messages.  But I generally either use variants or I create non-message object classes that I pass in messages (example: a dataset object, or job object, or fast-growing object).  The later have useful lifetimes longer than one message pass.

I'm not sure variants are that slow, btw, so I would benchmark before avoiding them.

Ah yea, I hadn't considered using an object. But since I was planning on passing a cluster, what difference does it make if it is an object or a plain cluster? Not much in the message passing regard.

But, packing the data in an object does open the door to created class methods to manipulate the data, which in turn could use the command-pattern for the ThreadPool. With that, it wouldn't be so much passing in a set of parameters and returning a separate result, but more passing the object through the ThreadPool and "pushing a button on it"-- very assembly line like in my mind.

I think I just realized the potential of the command pattern.

Share this post


Link to post
Share on other sites

I use an object only when I'm doing a lot more than just passing data in a single message.  So a "job" object might be sent to the "Worker" actor, who calls "do job", but then the completed "job" is passed on to another actor who calls methods to reads the results.   Or a "data" object might pass through several actors for processing and display.   If I just want to pass a loose collection of data from one actor to another then I just use a cluster.  But I find it rare to do this, and my messages tend to either be a single piece of data (or array) or a tight collection of data that makes sense to be an object.

Edited by drjdpowell

Share this post


Link to post
Share on other sites

Join the conversation

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

Guest
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.


  • Similar Content

    • By drjdpowell
      An extensive library for passing messages between parallel processes. Generalizes the communication method, allowing the message sender to use the method provided by the receiver. Supported communication methods include wrappings of simple queues, user events, and notifiers, as well a more complex channels such as a TCP server and client. In addition, one can configure simple forwarding addresses (“Observers"), which can send messages to multiple destinations, optionally with modifications such as adding a prefix to the message label, relabelling, or substituting a different message.
      Communication patterns supported include request-reply (asynchronous or synchronous), where the reply is sent to a "reply address" attached to the request, and register-notify, where one process sends a registration message to another in order to subscribe to a series of updates.  Also supports scatter-gather, the gathering of replies from multiple senders into an array of messages.
      An option framework for dynamically-launched VI "actors" is also provided, including example templates, which can be accessed via the Tools menu (from an open Project, select Tools>>Messenger Library>>Create Actor from Template..).  An "Actor Manager" debug tool is also installed under the Tools menu.  Please note that this package has nothing directly to do with the NI Actor Framework (other than both packages are influenced by the Actor Model).
      ***Introductory Videos are on a YouTube channel.***
      ***A great summary of many Messenger Library sources, provided by Bob W Edwards***
      Original conversation on this work is here.

      Now hosted on the LabVIEW Tools Network (but note that the latest version will often be on LAVA)
      ***NOTE: latest versions require VIPM 2017 or later to install.***
    • By drjdpowell
      I've started to make some instructional videos on YouTube for my Messenger Library.   I was inspired by Delacor's nice videos on their new DQMH framework and also by Steve Watts' CSLUG channel.  Any feedback appreciated.
       
      James
    • By drjdpowell
      I’m hoping to add some sample projects to my “Messenging” package, and I thought it would be easy and instructive to rework one of NI’s templates, “Continuous Measurement and Logging”, as it is already somewhat actor-like with three communicating modules.  Attached is a (back-saved for 2011) copy of the NI project, with my version included (run “Main.vi” for the original, “Main.lvclass:Actor.vi” for my version). 
       
       I kept the basic functionality the same, but couldn’t resist changing some of the UI (in the old code, “Main” controls the UI; in the new code, published state messages from the Acquisition and Logging Actors set the UI).
       
      Continuous Measurment and Logging with Messenging.zip

       
       Any comments appreciated.   Is this example less clear than the NI original?  Why?  How could I improve it?
       
      In particular, is code like this (the most complicated interaction, I think) understandable without heavy documentation?  It’s a “Start Logger, then Start Acquisition, then Unset the Busy Cursor” three-actor chain message:

      I’m thinking of making a “Send Chain Message” subVI (that accepts arrays of addresses and message labels) to replace the above code.
       
      — James
    • By torekp
      At http://zone.ni.com/d...a/epd/p/id/4394, NI provides some example code for using Windows Messaging in Labview 2009. But the example generates and intercepts the messages in the same single toplevel VI. Is it possible to converse between two VIs using Windows Messaging? Would I need (or be able) to create a new DLL in order to do that?
      Toplevel:

      Create Windows Message Queue:

      From the Readme file:
      **How it works**
      A DLL included does all of the dirty work. The VIs in the library are primarily
      wrappers around the DLL with the exception of Wait for Windows Message.vi.
      When creating the first Windows message queue, the DLL installs a windows Get Message Hook and a CallMsgProc Hook on the LabVIEW process. This allows the DLL to inspect all messages heading for LabVIEW before LabVIEW processes them. The hook function determines whether each individual message is a message in which the queue is interested. If it is, it adds the message to the queue, and sets an occurrence. The Wait on Windows Message.vi is waiting on the same occurrence, and thus it continues its execution, retrieving the message from the queue. A number of utility functions are also provided for working with the queue.
      --------
      Any advice appreciated, even if it's "abandon all hope". (I'm a very weak C programmer.) I'm attaching the CPP code for the DLL, as a text file.
      Windows Messages for LabVIEW.txt
×
×
  • Create New...

Important Information

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