diff --git a/legacy/evas/src/lib/cache/evas_preload.c b/legacy/evas/src/lib/cache/evas_preload.c index 34678e004e..0dfa5f9b15 100644 --- a/legacy/evas/src/lib/cache/evas_preload.c +++ b/legacy/evas/src/lib/cache/evas_preload.c @@ -15,6 +15,8 @@ #include "Evas.h" #ifdef BUILD_ASYNC_PRELOAD +typedef struct _Evas_Preload_Pthread_Worker Evas_Preload_Pthread_Worker; +typedef struct _Evas_Preload_Pthread_Data Evas_Preload_Pthread_Data; typedef void (*_evas_preload_pthread_func)(void *data); @@ -24,7 +26,7 @@ struct _Evas_Preload_Pthread_Worker _evas_preload_pthread_func func_end; _evas_preload_pthread_func func_cancel; - void *data; + const void *data; Eina_Bool cancel : 1; }; @@ -39,22 +41,18 @@ static int _evas_preload_thread_count_max = 0; #ifdef BUILD_ASYNC_PRELOAD static int _evas_preload_thread_count = 0; -static Eina_List *_evas_preload_thread_workers = NULL; +static Eina_List *_evas_preload_thread_data = NULL; static Eina_List *_evas_preload_thread = NULL; static LK(_mutex) = PTHREAD_MUTEX_INITIALIZER; static void -_evas_preload_thread_end(void *data) +_evas_preload_thread_end(Evas_Preload_Pthread_Data *pth) { - Evas_Preload_Pthread_Data *pth = data; Evas_Preload_Pthread_Data *p; - if (pthread_join(pth->thread, (void **)&p) != 0) - { - free(p); - return; - } + if (pthread_join(pth->thread, (void **) &p) != 0) + return ; _evas_preload_thread = eina_list_remove(_evas_preload_thread, pth); } @@ -68,47 +66,49 @@ _evas_preload_thread_done(void *target __UNUSED__, Evas_Callback_Type type __UNU if (work->cancel) { - if (work->func_cancel) work->func_cancel(work->data); + if (work->func_cancel) + work->func_cancel((void *) work->data); } else { - work->func_end(work->data); + work->func_end((void *) work->data); } free(work); } static void * -_evas_preload_thread_worker(void *data) +_evas_preload_thread_worker(Evas_Preload_Pthread_Data *pth) { - Evas_Preload_Pthread_Data *pth = data; Evas_Preload_Pthread_Worker *work; - + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - -on_error: - - for (;;) + + on_error: + + while (_evas_preload_thread_data) { LKL(_mutex); - if (!_evas_preload_thread_workers) + if (!_evas_preload_thread_data) { LKU(_mutex); break; } - work = eina_list_data_get(_evas_preload_thread_workers); - _evas_preload_thread_workers = eina_list_remove_list - (_evas_preload_thread_workers, _evas_preload_thread_workers); + work = eina_list_data_get(_evas_preload_thread_data); + _evas_preload_thread_data = eina_list_remove_list(_evas_preload_thread_data, _evas_preload_thread_data); + LKU(_mutex); - work->func_heavy(work->data); + + work->func_heavy((void *) work->data); + evas_async_events_put(pth, 0, work, _evas_preload_thread_done); } LKL(_mutex); - if (_evas_preload_thread_workers) + if (_evas_preload_thread_data) { LKU(_mutex); goto on_error; @@ -116,6 +116,18 @@ on_error: _evas_preload_thread_count--; LKU(_mutex); + + work = malloc(sizeof (Evas_Preload_Pthread_Worker)); + if (!work) return NULL; + + work->data = pth; + work->func_heavy = NULL; + work->func_end = (_evas_preload_pthread_func) _evas_preload_thread_end; + work->func_cancel = NULL; + work->cancel = EINA_FALSE; + + evas_async_events_put(pth, 0, work, _evas_preload_thread_done); + return pth; } #endif @@ -125,7 +137,7 @@ _evas_preload_thread_init(void) { _evas_preload_thread_count_max = eina_cpu_count(); if (_evas_preload_thread_count_max <= 0) - _evas_preload_thread_count_max = 1; + _evas_preload_thread_count_max = 1; } void @@ -141,26 +153,26 @@ _evas_preload_thread_shutdown(void) LKL(_mutex); - EINA_LIST_FREE(_evas_preload_thread_workers, work) + EINA_LIST_FREE(_evas_preload_thread_data, work) { - if (work->func_cancel) work->func_cancel(work->data); + if (work->func_cancel) + work->func_cancel((void *)work->data); free(work); } - + LKU(_mutex); - + EINA_LIST_FREE(_evas_preload_thread, pth) { Evas_Preload_Pthread_Data *p; - + pthread_cancel(pth->thread); - pthread_join(pth->thread, (void **)&p); - free(p); + pthread_join(pth->thread, (void **) &p); } #endif } -Evas_Preload_Pthread_Worker * +Evas_Preload_Pthread * evas_preload_thread_run(void (*func_heavy) (void *data), void (*func_end) (void *data), void (*func_cancel) (void *data), @@ -170,7 +182,7 @@ evas_preload_thread_run(void (*func_heavy) (void *data), Evas_Preload_Pthread_Worker *work; Evas_Preload_Pthread_Data *pth; - work = malloc(sizeof(Evas_Preload_Pthread_Worker)); + work = malloc(sizeof (Evas_Preload_Pthread_Worker)); if (!work) { func_cancel((void *)data); @@ -181,25 +193,25 @@ evas_preload_thread_run(void (*func_heavy) (void *data), work->func_end = func_end; work->func_cancel = func_cancel; work->cancel = EINA_FALSE; - work->data = (void *)data; + work->data = data; LKL(_mutex); - _evas_preload_thread_workers = eina_list_append - (_evas_preload_thread_workers, work); + _evas_preload_thread_data = eina_list_append(_evas_preload_thread_data, work); if (_evas_preload_thread_count == _evas_preload_thread_count_max) { - LKU(_mutex); - return work; + pthread_mutex_unlock(&_mutex); + return (Evas_Preload_Pthread*) work; } LKU(_mutex); /* One more thread could be created. */ - pth = malloc(sizeof(Evas_Preload_Pthread_Data)); - if (!pth) goto on_error; + pth = malloc(sizeof (Evas_Preload_Pthread_Data)); + if (!pth) + goto on_error; - if (!pthread_create(&pth->thread, NULL, _evas_preload_thread_worker, pth)) + if (pthread_create(&pth->thread, NULL, (void *) _evas_preload_thread_worker, pth) == 0) { #ifdef __linux__ struct sched_param param; @@ -229,13 +241,14 @@ evas_preload_thread_run(void (*func_heavy) (void *data), LKL(_mutex); _evas_preload_thread_count++; LKU(_mutex); - return work; + return (Evas_Preload_Pthread*) work; } on_error: if (_evas_preload_thread_count == 0) { - if (work->func_cancel) work->func_cancel(work->data); + if (work->func_cancel) + work->func_cancel((void *) work->data); free(work); } return NULL; @@ -244,39 +257,41 @@ evas_preload_thread_run(void (*func_heavy) (void *data), If no thread and as we don't want to break app that rely on this facility, we will lock the interface until we are done. */ - func_heavy(data); - func_end(data); + func_heavy((void *) data); + func_end((void *) data); - return NULL; + return EINA_TRUE; #endif } Eina_Bool -evas_preload_thread_cancel(Evas_Preload_Pthread_Worker *wk) +evas_preload_thread_cancel(Evas_Preload_Pthread *thread) { #ifdef BUILD_ASYNC_PRELOAD Evas_Preload_Pthread_Worker *work; Eina_List *l; - if (!wk) return EINA_TRUE; - LKL(_mutex); - EINA_LIST_FOREACH(_evas_preload_thread_workers, l, work) - { - if (work != wk) continue; - _evas_preload_thread_workers = eina_list_remove_list - (_evas_preload_thread_workers, l); - LKU(_mutex); - if (work->func_cancel) work->func_cancel(work->data); - free(work); - return EINA_TRUE; - } + EINA_LIST_FOREACH(_evas_preload_thread_data, l, work) + if ((void *) work == (void *) thread) + { + _evas_preload_thread_data = eina_list_remove_list(_evas_preload_thread_data, l); + + LKU(_mutex); + + if (work->func_cancel) + work->func_cancel((void *) work->data); + free(work); + + return EINA_TRUE; + } LKU(_mutex); /* Delay the destruction */ - wk->cancel = EINA_TRUE; + work = (Evas_Preload_Pthread_Worker *) thread; + work->cancel = EINA_TRUE; return EINA_FALSE; #else return EINA_TRUE; diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index db4cebd408..7d4b1941d2 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -374,8 +374,7 @@ typedef struct _Image_Entry Image_Entry; typedef struct _Image_Entry_Flags Image_Entry_Flags; typedef struct _Engine_Image_Entry Engine_Image_Entry; typedef struct _Evas_Cache_Target Evas_Cache_Target; -typedef struct _Evas_Preload_Pthread_Worker Evas_Preload_Pthread_Worker; -typedef struct _Evas_Preload_Pthread_Data Evas_Preload_Pthread_Data; +typedef struct _Evas_Preload_Pthread Evas_Preload_Pthread; typedef struct _RGBA_Image_Loadopts RGBA_Image_Loadopts; #ifdef BUILD_PIPE_RENDER @@ -530,8 +529,8 @@ struct _Image_Entry const char *file; const char *key; - Evas_Cache_Target *targets; - Evas_Preload_Pthread_Worker *preload; + Evas_Cache_Target *targets; + Evas_Preload_Pthread *preload; time_t timestamp; time_t laststat; diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index 83a5efc562..d28c47f799 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -801,12 +801,11 @@ int evas_async_target_del(const void *target); void _evas_preload_thread_init(void); void _evas_preload_thread_shutdown(void); -Evas_Preload_Pthread_Worker *evas_preload_thread_run - (void (*func_heavy)(void *data), - void (*func_end)(void *data), - void (*func_cancel)(void *data), - const void *data); -Eina_Bool evas_preload_thread_cancel(Evas_Preload_Pthread_Worker *thread); +Evas_Preload_Pthread *evas_preload_thread_run(void (*func_heavy)(void *data), + void (*func_end)(void *data), + void (*func_cancel)(void *data), + const void *data); +Eina_Bool evas_preload_thread_cancel(Evas_Preload_Pthread *thread); void _evas_walk(Evas *e); void _evas_unwalk(Evas *e);