Trampolines are free[1] so you can add as many as you like.
[1] Meaning that if you don’t use them, they take no space.
Trampolines are free[1] so you can add as many as you like.
[1] Meaning that if you don’t use them, they take no space.
Ok I’m confused again. Help?
I’m just trying to exit a mode onreturn.
If I follow correctly, I should be able to just do popMode();, and since it’s the mode I arrived in, it should exit the mode system… No?
Nothing is working right. The board freezes.
I could provide details of the inheritence and such, but I feel that might be a waste and the answer is "it doesn’t work like that?
code in question:
void mode_activate(bool onreturn) override {
if (onreturn) {
popMode();
} else {
PVLOG_NORMAL << "** Editing blade length.\n";
mode::getSL<SPEC>()->SaySelectBlade();
SPEC::SteppedMode::mode_activate(onreturn);
highlighted_blade_.Start(current_blade());
PVLOG_NORMAL << "** Highlighting blade: " << current_blade() << "\n";
}
}
Instead of popMode(), I grasped for straws and tried
SPEC::MenuBase::exit(),
SPEC::SteppedMode::exit();
No bueno.
Maybe current_mode or current_mode->previous_is a nullptr?
Seems like a thing that should work. Looking at popMode() and your code, I can’t see an obvious reason why it wouldn’t. A debugger would tell you what the problem is pretty much immediately I think. (Don’t remember if you have a debugger set up.)
Another possibility is that current_mode->previous_ is equal to this. (Circular list)
I think popping again too soon isn’t giving current_mode->mode_activate(true);
enough time to finish.
Any good way to wait a moment before trying to popMode() again?
oh… it might be looping on itself. hmmm.
That’s not how it works.
There is no “too soon”, because everything happen after each other, in the order specified. Two things are never going on at the same time. [1][2]
In your case, popMode() will call mode_activate which will call popMode() again, but then things will return one step at a time, and popMode doesn’t do anything after mode_activate returns, so nothing bad should happen.
Now if current_mode or current_mode->previous_ is messed up, that’s probably due to a problem somewhere else. For instance, there could be too few pushMode() calls, or something doing pushMode() on itself.
[1] State machines makes it seem like things are happening at the same time, but they don.t
[2] Interrupts can happen at any time, which kind of counts as “at the same time”, but there are no interrupts involved in Modes.
Within the mode stack, no. However, mode_deactivate calls prop_UpdateStyle, which I know can take a few moments.
I did see "Style RAM = " sneak in a couple of times during freezes before the output messages stopped.
So I think it’s that.
popMode() finishes, but the UpdateStyle hasn’t yet, and then gets called again “too soon”
Or… maybe it’s hating tryng to highlighted_blade_.Stop(current_blade());
when it hasn’t been started again yet.
Now I’m just thinking out loud and documenting here for my reference.
This is as far as I’ve gotten:
I hooked up debugging and inexplicably, popMode() keeps calling mode_activate in the BCSelectBladeMode instead of exiting the mode stack, regardless of the previous_ poiniter being set correctly (so we know nothing is further back because we’re at the base)
Initial Push into BCSelectBladeMode:
10:31:06.295 -> Pushing mode: current_mode = 0x536879172, new mode = 0x536898920
10:31:06.295 -> pushMode: previous_ set to 0x536879172
10:31:06.295 -> BCSelectBladeMode: Entering mode_activate, onreturn=0
Mode Stack at this point:
current_mode: 0x536898920 → BCSelectBladeMode.
current_mode->previous_: 0x536879172 → Likely SaberBCButtons.
Push into BCChangeBladeLengthBlade1:
10:31:09.017 -> Pushing mode: current_mode = 0x536898920, new mode = 0x536897004
10:31:09.017 -> pushMode: previous_ set to 0x536898920
Mode Stack at this point:
current_mode: 0x536897004 → BCChangeBladeLengthBlade1.
current_mode->previous_: 0x536898920 → BCSelectBladeMode.
Pop from BCChangeBladeLengthBlade1:
10:31:15.048 -> popMode: Starting...
10:31:15.048 -> popMode: Deactivating current_mode = 0x536897004, previous_ = 0x536898920
At this point, popMode() switches back to BCSelectBladeMode and activates it with onreturn = true:
10:31:15.083 -> popMode: Activating previous mode = 0x536898920
10:31:15.083 -> BCSelectBladeMode: Entering mode_activate, onreturn=1
BCSelectBladeMode Handles onreturn = true:
10:31:15.083 -> BCSelectBladeMode: onreturn is true, calling popMode()...
BCSelectBladeMode calls popMode() again, moving back to the previous mode (SaberBCButtons):
10:31:15.083 -> popMode: Deactivating current_mode = 0x536898920, previous_ = 0x536879172
10:31:15.083 -> popMode: Switching to previous mode
10:31:15.083 -> popMode: Activating previous mode = 0x536879172
Unexpected Behavior: Despite popMode() transitioning to SaberBCButtons (0x536879172), we see this next:
10:31:15.083 -> BCSelectBladeMode: Returned from popMode(), continuing flow...
10:31:15.083 -> ** Editing blade length.
10:31:15.083 -> ** Highlighting blade: 1
This indicates that BCSelectBladeMode::mode_activate is being re-entered, despite current_mode now being SaberBCButtons.
It’s true that prop_UpdateStyle can take a bit of time, but that doesn’t change anything. Nothing else happens while prop_UpdateStyle is working.
I think the Start() and Stop() have to be balanced, or you get a crash.
It seems to me that this sequence of printouts should be impossible.
Before “Editing blade length”, there should always be a line like this:
BCSelectBladeMode: Entering mode_activate, onreturn=0
right? (or have I misunderstood where your printouts are?)
The “else” is still there in mode_activate, right?
What compiler are you using?
Maybe try a different version…
Thank you.