PEG Get Timer Event event if timer killed

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PEG Get Timer Event event if timer killed

Jump to solution
513 Views
arnogir
Senior Contributor II

Hello,

I start the project with peg 5 years ago, And at this time, there was a support via email.

Today, this email is broken!

So I ask the question here.

 

I’m facing a problem with the PEG which lead to a µC crash.

 

I’m on a Kinetis K70 with MQX 4.2, PEG lite 2.4.

 

I’m on a screen in which I start a timer when I press a PegButton:

 

case PEG_SIGNAL(ID_AP_SCREEN_Cleaning_ConfirmButton, PSF_CLICKED):
       
// WB_AUTO_GEN  Enter your code here:
….       
          SetTimer(AP_SCREEN_CLEANING_TIMER_ANIMATION, PEG_ONE_SECOND
/10, PEG_ONE_SECOND/10);
       
}

 

On another button, I select in the PegBuilder it should make a “switch to” the RootWindow, then the generated code is following:

 

case PEG_SIGNAL(ID_AP_SCREEN_Cleaning_CancelButton, PSF_CLICKED):
       
{
        PegWindow *pw
= new rootwindow(0, 0);
        Parent()
->Add(pw);
       
}
        Destroy(
this);
       
// WB_AUTO_GEN Enter your code here:
        KillTimer(AP_SCREEN_CLEANING_TIMER_ANIMATION);
       
return ID_AP_SCREEN_Cleaning_CancelButton;      /* WB_AUTO_GEN End case */

 

You can see the generated code, switch to the RootWindow, and destroy the current view.

After that, I kill the created timer.

 

But, in some case, I think the Timer event was already into the queue when the timer is killed.

Then, I get later event timer, in which for some reason, I do the following:

 

case PM_TIMER:
   
{
     
if (Mesg.Param == AP_SCREEN_CLEANING_TIMER_ANIMATION)
     
{       
        ….
       
if (AP_Clean_GetState() == AP_CLEAN_IDLE)
       
{
          ….

          PegWindow *pw = new rootwindow(0, 0);
          Parent()
->Add(pw);
          Destroy(
this);
          KillTimer(AP_SCREEN_CLEANING_TIMER_ANIMATION);
       
}
        CheckDefault();
     
}
      
return PegWindow::Message(Mesg);

In fact, it is a supervision timer which check a state of my application. If state is Idle, I should quit the current view and return to the root window.

Then, Like the event timer was into the queue before I press the cancel button, I also get the timer event in which I also create the rootwindow and destry(this)

So this part is done twice time! Then I obtain a µC crash on the Parent()->Add(pw);

 

Could you advise me if there are a simple way to discard all the selected timer event into the queue when I Kill them?

Labels (1)
0 Kudos
1 Solution
455 Views
arnogir
Senior Contributor II

I'm allow me to place here the answer from PEG support:

I'm a engineer of PEG team. Glad to assist you.

 

Here is the code of Destroy function:

 

        Presentation()->ThingDestroyed(pWhat);

        TimerManager()->KillTimer(pWhat, 0, TRUE);

        MessageQueue()->Purge(pWhat);    // no more messages for this guy!

        delete pWhat;

        pWhat = NULL;

 

As you can see here, Destroy function iftself will delete the timer, purge all related messages in MessageQueue.

So you needn't to call KillTimer after Destroy function.

 

You are handling two asynchromous events (Button click and Timer). Both of them are able to destroy the current windows. So, to ensure the code run correctly, please add a FLAG (ex. FLAG_ON_DESTROYING) to monitor the status of the window. Because although you call to Destroy function, the object will not be destroyed immediately. We only add new rootwindow and destroy current window in case of FLAG_ON_DESTROYING = false.

 

Hope that helps.

...

Finally, I could reproduce your situation on my side by adding a Timer event directly before calling Destroy function.

 

Add I said, when you call Destroy function, the Object can be either deleted immediately or push to garbage collector depend on the running context. That means destroy steps (include killing timer and purging messages) can be implemented immediately or later. In the case of the second condition, a Timer event can be add to Queue before the garbage collector really delete the object. That why Timer handler still be called after Destroy method.

 

I agree that this may be a issue of the garbage collector. We will find the way to improve its mechanism.

The code shoud like as below:

 

In the window construction:

....

FLAG_ON_DESTROYING = false;

 

In Message handler:

 

case PEG_SIGNAL(ID_ReturnButton, PSF_CLICKED):

         if(FLAG_ON_DESTROYNG == false)
        {

        FLAG_ON_DESTROYNG = true;


        PegWindow *pw = new rootwindow(00);
        Parent()
->Add(pw);

        Destroy(this);
        
}
        return ID_ReturnButton;

 

case PM_TIMER:

        if(FLAG_ON_DESTROYNG == false)

      {

             FLAG_ON_DESTROYNG = true;

 

             PegWindow *pw = new rootwindow(0, 0);

             Parent()->Add(pw);

             Destroy(this);

       }

        break;

 

View solution in original post

0 Kudos
1 Reply
456 Views
arnogir
Senior Contributor II

I'm allow me to place here the answer from PEG support:

I'm a engineer of PEG team. Glad to assist you.

 

Here is the code of Destroy function:

 

        Presentation()->ThingDestroyed(pWhat);

        TimerManager()->KillTimer(pWhat, 0, TRUE);

        MessageQueue()->Purge(pWhat);    // no more messages for this guy!

        delete pWhat;

        pWhat = NULL;

 

As you can see here, Destroy function iftself will delete the timer, purge all related messages in MessageQueue.

So you needn't to call KillTimer after Destroy function.

 

You are handling two asynchromous events (Button click and Timer). Both of them are able to destroy the current windows. So, to ensure the code run correctly, please add a FLAG (ex. FLAG_ON_DESTROYING) to monitor the status of the window. Because although you call to Destroy function, the object will not be destroyed immediately. We only add new rootwindow and destroy current window in case of FLAG_ON_DESTROYING = false.

 

Hope that helps.

...

Finally, I could reproduce your situation on my side by adding a Timer event directly before calling Destroy function.

 

Add I said, when you call Destroy function, the Object can be either deleted immediately or push to garbage collector depend on the running context. That means destroy steps (include killing timer and purging messages) can be implemented immediately or later. In the case of the second condition, a Timer event can be add to Queue before the garbage collector really delete the object. That why Timer handler still be called after Destroy method.

 

I agree that this may be a issue of the garbage collector. We will find the way to improve its mechanism.

The code shoud like as below:

 

In the window construction:

....

FLAG_ON_DESTROYING = false;

 

In Message handler:

 

case PEG_SIGNAL(ID_ReturnButton, PSF_CLICKED):

         if(FLAG_ON_DESTROYNG == false)
        {

        FLAG_ON_DESTROYNG = true;


        PegWindow *pw = new rootwindow(00);
        Parent()
->Add(pw);

        Destroy(this);
        
}
        return ID_ReturnButton;

 

case PM_TIMER:

        if(FLAG_ON_DESTROYNG == false)

      {

             FLAG_ON_DESTROYNG = true;

 

             PegWindow *pw = new rootwindow(0, 0);

             Parent()->Add(pw);

             Destroy(this);

       }

        break;

 

0 Kudos