I have a situation where we would like to halt execution of a number of AOs at an arbitrary point in the state machine. The goal is to have the AOs stop execution in any state, where the exit criteria of states is not executed when the stop is commanded.
I attempted to accomplish this be posting a signal to the AOs, and having the AOs unsubscirbeAll() and then issue a QActive_stop() to themselves. However, this resulted in a couple of those AOs generating a faultISR (on a Tiva 129 series processor). Apparently, there was at least one event left on the AOs queue after the stop was executed, causing the fault. I can reorder the AOs to keep the fault from occurring, but this is a very clumsy and error prone way of managing the AOs.
I would like to do it by exiting to an "idle" state as suggested in that post, but getting to that idle state, particularly in a complex state machine, without having the states' exit criteria being executed, is prohibitively complex. Is there a way I can get AOs to enter an idle state and guarantee those AOs won't execute the previous states' exit code?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As I tried to explain in the other discusssion thread that you quote, calling QActive_stop() should be the last resort. From your description of the problem, I'm not sure that this is what you want. It seems to me that you simply wish to pause a couple of AOs for a while.
But pehraps you could approach this problem from the other end. I mean, as long as an AO does not receive events, it is effectively "frozen" it its current state. So, perhaps you could design your system such that when you wish to "pause", you stop producing events to the specific group of AOs. Wouldn't that be easier?
Actually, an example of this approach is provided in the "extended" DPP example (Dining Philosopher Problem), which is available for all supported CPUs and RTOSes. The "extension" of DPP is that the application can be "paused", in which Philosophers stop eating. Instead of messing up with all 5 Philosophers, however, the feature is implemented in the Table AO, which simply stops granting the permissions to eat.
--MMS
Last edit: Quantum Leaps 2015-09-03
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
We effectively have 3 tiers of AOs. The first tier controls hardware. The second tier are AOs that provide some type of service, utilizing one or more of the first tier AOs. The third tier are managers that decide which services should be running. The 2nd tiers are not necessarily orthogonal, and more than one 2nd tier may be controlling a 1st tier AO. Normally the 1st tier is abstracted from the 3rd tier.
In a safety situation, we want to immediately stop all services (2nd tier), and then control the 1st tier via the 3rd tier directly in a specified fashion - depending on what the safety situation is. One of our architects describes it as a "hands-off" of the 2nd tier AOs.
Since there are so many lines of communications between these AOs, there is a complex web of AO handles that have been passed to each other. Essentially we are trying to "freeze" the 2nd tier AOs, using your words, but if they are in a true operational state, then they are in the midst of executing their state machines. I need to get all of these AOs to stop in place, so the first tier AOs can take action.
I have no clean way of passing a message that says "stop what you are doing, and leave all hardware exactly as it is right now". The stop() method would work, if I could flush the event queues. But as you have already pointed out, that method is really not designed to accomplish what I'm tyring to do. But I havn't discovered a better way of doing this, short of putting a lot more complexity into the 2nd tier AOs.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It would seem to me ALL AOs and subordinate HSM's should have a "Clean" way to transion back to idle for any state they could be in for some time. This should be the design pattern. If it is just an issue of bypassing a nested states exit criteria you can set a "stop" flag on the signals transition and bypass exit stuff on the way back out but that is probably not the ideal design.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If your "tier-2" AOs receive events via publish-subscribe, you could simply call QActive_unsubscribeAll() for all these AOs. This would cut them off the communication, and effectively "freeze" them in their current state. To resume communication, each of those AOs would need to subscribe again to its events, but you might wrap all such subscriptions in a function for each AO. I hope you get the idea.
On a side note, it seems to me that this "special stopped mode" for your "tier-2" AOs is defeating your own layered design policy. I mean, the whole purpose of layered design is to limit coupling and dependencies to only a layer immediately above and immediately below. You apparently cross the layers here (big bowl of spaghetti?). From experience, such things always tend to backfire in the future.
So, what I'm trying to say is that I wouldn't blame QP for not "playing along" with this back-door solution. A good piece of software is supposed to be easy to use right and hard to use wrong. Your use seems to fall on the "wrong" side, so QP is not obligated to be "easy" to use for this. I hope that this makes sense to you.
--MMS
Last edit: Quantum Leaps 2015-09-04
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have a situation where we would like to halt execution of a number of AOs at an arbitrary point in the state machine. The goal is to have the AOs stop execution in any state, where the exit criteria of states is not executed when the stop is commanded.
I attempted to accomplish this be posting a signal to the AOs, and having the AOs unsubscirbeAll() and then issue a QActive_stop() to themselves. However, this resulted in a couple of those AOs generating a faultISR (on a Tiva 129 series processor). Apparently, there was at least one event left on the AOs queue after the stop was executed, causing the fault. I can reorder the AOs to keep the fault from occurring, but this is a very clumsy and error prone way of managing the AOs.
On reading in this forum, I see where Miro commented on something similar here:
http://sourceforge.net/p/qpc/discussion/668726/thread/a32d7ca8/#4b91
I would like to do it by exiting to an "idle" state as suggested in that post, but getting to that idle state, particularly in a complex state machine, without having the states' exit criteria being executed, is prohibitively complex. Is there a way I can get AOs to enter an idle state and guarantee those AOs won't execute the previous states' exit code?
As I tried to explain in the other discusssion thread that you quote, calling
QActive_stop()should be the last resort. From your description of the problem, I'm not sure that this is what you want. It seems to me that you simply wish to pause a couple of AOs for a while.But pehraps you could approach this problem from the other end. I mean, as long as an AO does not receive events, it is effectively "frozen" it its current state. So, perhaps you could design your system such that when you wish to "pause", you stop producing events to the specific group of AOs. Wouldn't that be easier?
Actually, an example of this approach is provided in the "extended" DPP example (Dining Philosopher Problem), which is available for all supported CPUs and RTOSes. The "extension" of DPP is that the application can be "paused", in which
Philosophersstop eating. Instead of messing up with all 5Philosophers, however, the feature is implemented in theTableAO, which simply stops granting the permissions to eat.--MMS
Last edit: Quantum Leaps 2015-09-03
The problem we are trying to solve is thus:
We effectively have 3 tiers of AOs. The first tier controls hardware. The second tier are AOs that provide some type of service, utilizing one or more of the first tier AOs. The third tier are managers that decide which services should be running. The 2nd tiers are not necessarily orthogonal, and more than one 2nd tier may be controlling a 1st tier AO. Normally the 1st tier is abstracted from the 3rd tier.
In a safety situation, we want to immediately stop all services (2nd tier), and then control the 1st tier via the 3rd tier directly in a specified fashion - depending on what the safety situation is. One of our architects describes it as a "hands-off" of the 2nd tier AOs.
Since there are so many lines of communications between these AOs, there is a complex web of AO handles that have been passed to each other. Essentially we are trying to "freeze" the 2nd tier AOs, using your words, but if they are in a true operational state, then they are in the midst of executing their state machines. I need to get all of these AOs to stop in place, so the first tier AOs can take action.
I have no clean way of passing a message that says "stop what you are doing, and leave all hardware exactly as it is right now". The stop() method would work, if I could flush the event queues. But as you have already pointed out, that method is really not designed to accomplish what I'm tyring to do. But I havn't discovered a better way of doing this, short of putting a lot more complexity into the 2nd tier AOs.
It would seem to me ALL AOs and subordinate HSM's should have a "Clean" way to transion back to idle for any state they could be in for some time. This should be the design pattern. If it is just an issue of bypassing a nested states exit criteria you can set a "stop" flag on the signals transition and bypass exit stuff on the way back out but that is probably not the ideal design.
If your "tier-2" AOs receive events via publish-subscribe, you could simply call
QActive_unsubscribeAll()for all these AOs. This would cut them off the communication, and effectively "freeze" them in their current state. To resume communication, each of those AOs would need to subscribe again to its events, but you might wrap all such subscriptions in a function for each AO. I hope you get the idea.On a side note, it seems to me that this "special stopped mode" for your "tier-2" AOs is defeating your own layered design policy. I mean, the whole purpose of layered design is to limit coupling and dependencies to only a layer immediately above and immediately below. You apparently cross the layers here (big bowl of spaghetti?). From experience, such things always tend to backfire in the future.
So, what I'm trying to say is that I wouldn't blame QP for not "playing along" with this back-door solution. A good piece of software is supposed to be easy to use right and hard to use wrong. Your use seems to fall on the "wrong" side, so QP is not obligated to be "easy" to use for this. I hope that this makes sense to you.
--MMS
Last edit: Quantum Leaps 2015-09-04