lv_anim bugfix: was error when the object is delete end callback

This commit is contained in:
Gabor Kiss-Vamosi
2018-06-22 22:58:26 +02:00
parent a659d40202
commit 7503242a6a
2 changed files with 35 additions and 24 deletions

View File

@@ -36,6 +36,7 @@ static bool anim_ready_handler(lv_anim_t * a);
**********************/ **********************/
static lv_ll_t anim_ll; static lv_ll_t anim_ll;
static uint32_t last_task_run; static uint32_t last_task_run;
static bool anim_list_changed;
/********************** /**********************
* MACROS * MACROS
@@ -85,9 +86,9 @@ void lv_anim_create(lv_anim_t * anim_p)
*/ */
bool lv_anim_del(void * var, lv_anim_fp_t fp) bool lv_anim_del(void * var, lv_anim_fp_t fp)
{ {
bool del = false;
lv_anim_t * a; lv_anim_t * a;
lv_anim_t * a_next; lv_anim_t * a_next;
bool del = false;
a = lv_ll_get_head(&anim_ll); a = lv_ll_get_head(&anim_ll);
while(a != NULL) { while(a != NULL) {
/*'a' might be deleted, so get the next object while 'a' is valid*/ /*'a' might be deleted, so get the next object while 'a' is valid*/
@@ -96,6 +97,7 @@ bool lv_anim_del(void * var, lv_anim_fp_t fp)
if(a->var == var && (a->fp == fp || fp == NULL)) { if(a->var == var && (a->fp == fp || fp == NULL)) {
lv_ll_rem(&anim_ll, a); lv_ll_rem(&anim_ll, a);
lv_mem_free(a); lv_mem_free(a);
anim_list_changed = true; /*Read by `anim_task`. It need to know if a delete occurred in the linked list*/
del = true; del = true;
} }
@@ -197,16 +199,22 @@ static void anim_task(void * param)
{ {
(void)param; (void)param;
volatile uint32_t elaps;
elaps = lv_tick_elaps(last_task_run);
lv_anim_t * a; lv_anim_t * a;
lv_anim_t * a_next; LL_READ(anim_ll, a) {
a = lv_ll_get_head(&anim_ll); a->has_run = 0;
while(a != NULL) { }
/*'a' might be deleted, so get the next object while 'a' is valid*/
a_next = lv_ll_get_next(&anim_ll, a);
uint32_t elaps = lv_tick_elaps(last_task_run);
a = lv_ll_get_head(&anim_ll);
while(a != NULL) {
/*It can be set by `lv_anim_del()` typically in `end_cb`. If set then an animation delete happened in `anim_ready_handler`
* which could make this linked list reading corrupt because the list is changed meanwhile
*/
anim_list_changed = false;
if(!a->has_run) {
a->has_run = 1; /*The list readying might be reseted so need to know which anim has run already*/
a->act_time += elaps; a->act_time += elaps;
if(a->act_time >= 0) { if(a->act_time >= 0) {
if(a->act_time > a->time) a->act_time = a->time; if(a->act_time > a->time) a->act_time = a->time;
@@ -221,8 +229,12 @@ static void anim_task(void * param)
anim_ready_handler(a); anim_ready_handler(a);
} }
} }
}
a = a_next; /* If the linked list changed due to anim. delete then it's not safe to continue
* the reading of the list from here -> start from the head*/
if(anim_list_changed) a = lv_ll_get_head(&anim_ll);
else a = lv_ll_get_next(&anim_ll, a);
} }
last_task_run = lv_tick_get(); last_task_run = lv_tick_get();
@@ -232,11 +244,10 @@ static void anim_task(void * param)
* Called when an animation is ready to do the necessary thinks * Called when an animation is ready to do the necessary thinks
* e.g. repeat, play back, delete etc. * e.g. repeat, play back, delete etc.
* @param a pointer to an animation descriptor * @param a pointer to an animation descriptor
* @return true: animation delete occurred * @return true: animation delete occurred nnd the `anim_ll` has changed
* */ * */
static bool anim_ready_handler(lv_anim_t * a) static bool anim_ready_handler(lv_anim_t * a)
{ {
bool invalid = false;
/*Delete the animation if /*Delete the animation if
* - no repeat and no play back (simple one shot animation) * - no repeat and no play back (simple one shot animation)
@@ -252,7 +263,6 @@ static bool anim_ready_handler(lv_anim_t * a)
/* Check if an animation is deleted in the cb function /* Check if an animation is deleted in the cb function
* if yes then the caller function has to know this*/ * if yes then the caller function has to know this*/
if(cb != NULL) cb(p); if(cb != NULL) cb(p);
invalid = true;
} }
/*If the animation is not deleted then restart it*/ /*If the animation is not deleted then restart it*/
else { else {
@@ -272,6 +282,6 @@ static bool anim_ready_handler(lv_anim_t * a)
} }
} }
return invalid; return anim_list_changed;
} }
#endif #endif

View File

@@ -51,6 +51,7 @@ typedef struct _lv_anim_t
uint8_t repeat :1; /*Repeat the animation infinitely*/ uint8_t repeat :1; /*Repeat the animation infinitely*/
/*Animation system use these - user shouldn't set*/ /*Animation system use these - user shouldn't set*/
uint8_t playback_now :1; /*Play back is in progress*/ uint8_t playback_now :1; /*Play back is in progress*/
uint32_t has_run :1; /*Indicates the animation has run it this round*/
} lv_anim_t; } lv_anim_t;
/*Example initialization /*Example initialization