I am developing a real-time application, and am utilizing an object oriented approach. The design pattern is similar to the Actor framework, but custom built. The class structure is setup to support several different subsystems, with the highest class being a "subsystem" class. Currently, I have only one motion sub-class just to verify inheritance, but my problem is with the subsystem class.
Each subsystem object has a few parameters, one of them being an "Execution Queue". It is a queue of 1D string arrays which tell the subsystem what to do on the next trigger. Each subsystem is launched in a manner similar to the actor framework (I used "Launch Actor Core.vi" as a guide, so this means using an Asynchronous Call By Reference (ACBR). I simplified it for my purposes and also closed out the reference which the actor vi does not do (I had problems even when was leaving the reference open), see below image.
The "SETUP" VI you see in the image is where the queue is initialized, I won't include that code as it's pretty straightforward. I have verified that the queue is created properly. None of my downstream code from the launch modifies the queue, it only accesses the queue. When I try to perform any operations on the queue after the launch VI, I receive the following: "Get Queue Status in Subsystem.lvclass:Message Handler.vi:640018->Subsystem.lvclass:Controller.vi:4750017->Subsystem.lvclass:Controller.vi.ACBRProxyCaller.A84000DB".
I receive similar messages for any queue operations I attempt to perform. I have also verified that - for the operations where I receive an error - I have the same reference that was created during setup where my queue operations performed successfully. The only difference between the setup VI's and my problem VI's is that the problem VI's are within the VI that I call through the ACBR.
Any help you could provide to me as to what I'm doing wrong or if I'm attempting to do something that can't be done would be greatly appreciated!
Solved! Go to Solution.
If you actually tried to mimic the Actor Framework, you would have seen a comment in there explaining why the launched actor needs to create the queue. Bascially, as soon as this launch VI's hierarchy is completed, it is removed from memory. This includes any references it created. So when the Launch is completed, your queue reference becomes invalid. Simple fix: make the actor that is called create the queue as part of its initialization. Then the queue will be valid as long as that actor is active.
So you're analysis seems to be correct, when I move the "SETUP" vi into the "CTRL LOOP" vi, the queues function correctly.
Are you referring to this comment from the AF: "By having each VI (caller and actor) create the the queue on which it receives messages, we guarantee that the lifetime of each queue is the same as the recipient, which means that the sender can enqueue a final Stop message to the receiver and then exit without worrying that the queue will be destroyed before the recipient gets the message. "
This comment is referring to the message queues, which I was implementing slightly differently so I ignored it (also my message queues are created within the CTRL LOOP vi so they were functioning as expected. I am not sure I understand why the queue reference is destroyed once the launch VI is terminated, I would appreciate if you could elaborate slightly on this.
Thank you for the quick response and solution!
bbarrett90 wrote: I am not sure I understand why the queue reference is destroyed once the launch VI is terminated, I would appreciate if you could elaborate slightly on this.
Here is an old thread with the same issue: When do VI and queue references become invalid?
Yes, this helps to clear it up a little more. I did find a second cause of the problem, I was launching my message handler by reference, and then launching my subsystems within the same "launcher" VI, but that launcher VI ultimately stops running and only the message handler remains active. So, when the "launcher" vi stopped, the queue references it had opened were automatically released, even though the reference was passed into an array of objects which was sent to the message handler.
I think I understand the mechanism behind the failure now, thank you for your assistance!