major clean of the preload stuff. leaks. bugs. nastinessesssss...

SVN revision: 52028
This commit is contained in:
Carsten Haitzler 2010-09-09 06:31:29 +00:00
parent c69628f5af
commit 4975395633
3 changed files with 71 additions and 84 deletions

View File

@ -15,8 +15,6 @@
#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);
@ -26,7 +24,7 @@ struct _Evas_Preload_Pthread_Worker
_evas_preload_pthread_func func_end;
_evas_preload_pthread_func func_cancel;
const void *data;
void *data;
Eina_Bool cancel : 1;
};
@ -41,18 +39,22 @@ 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_data = NULL;
static Eina_List *_evas_preload_thread_workers = NULL;
static Eina_List *_evas_preload_thread = NULL;
static LK(_mutex) = PTHREAD_MUTEX_INITIALIZER;
static void
_evas_preload_thread_end(Evas_Preload_Pthread_Data *pth)
_evas_preload_thread_end(void *data)
{
Evas_Preload_Pthread_Data *pth = data;
Evas_Preload_Pthread_Data *p;
if (pthread_join(pth->thread, (void **) &p) != 0)
return ;
if (pthread_join(pth->thread, (void **)&p) != 0)
{
free(p);
return;
}
_evas_preload_thread = eina_list_remove(_evas_preload_thread, pth);
}
@ -66,49 +68,47 @@ _evas_preload_thread_done(void *target __UNUSED__, Evas_Callback_Type type __UNU
if (work->cancel)
{
if (work->func_cancel)
work->func_cancel((void *) work->data);
if (work->func_cancel) work->func_cancel(work->data);
}
else
{
work->func_end((void *) work->data);
work->func_end(work->data);
}
free(work);
}
static void *
_evas_preload_thread_worker(Evas_Preload_Pthread_Data *pth)
_evas_preload_thread_worker(void *data)
{
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:
while (_evas_preload_thread_data)
on_error:
for (;;)
{
LKL(_mutex);
if (!_evas_preload_thread_data)
if (!_evas_preload_thread_workers)
{
LKU(_mutex);
break;
}
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);
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);
LKU(_mutex);
work->func_heavy((void *) work->data);
work->func_heavy(work->data);
evas_async_events_put(pth, 0, work, _evas_preload_thread_done);
}
LKL(_mutex);
if (_evas_preload_thread_data)
if (_evas_preload_thread_workers)
{
LKU(_mutex);
goto on_error;
@ -116,18 +116,6 @@ _evas_preload_thread_worker(Evas_Preload_Pthread_Data *pth)
_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
@ -137,7 +125,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
@ -153,26 +141,26 @@ _evas_preload_thread_shutdown(void)
LKL(_mutex);
EINA_LIST_FREE(_evas_preload_thread_data, work)
EINA_LIST_FREE(_evas_preload_thread_workers, work)
{
if (work->func_cancel)
work->func_cancel((void *)work->data);
if (work->func_cancel) work->func_cancel(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);
pthread_join(pth->thread, (void **)&p);
free(p);
}
#endif
}
Evas_Preload_Pthread *
Evas_Preload_Pthread_Worker *
evas_preload_thread_run(void (*func_heavy) (void *data),
void (*func_end) (void *data),
void (*func_cancel) (void *data),
@ -182,7 +170,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);
@ -193,25 +181,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 = data;
work->data = (void *)data;
LKL(_mutex);
_evas_preload_thread_data = eina_list_append(_evas_preload_thread_data, work);
_evas_preload_thread_workers = eina_list_append
(_evas_preload_thread_workers, work);
if (_evas_preload_thread_count == _evas_preload_thread_count_max)
{
pthread_mutex_unlock(&_mutex);
return (Evas_Preload_Pthread*) work;
LKU(_mutex);
return 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, (void *) _evas_preload_thread_worker, pth) == 0)
if (!pthread_create(&pth->thread, NULL, _evas_preload_thread_worker, pth))
{
#ifdef __linux__
struct sched_param param;
@ -241,14 +229,13 @@ evas_preload_thread_run(void (*func_heavy) (void *data),
LKL(_mutex);
_evas_preload_thread_count++;
LKU(_mutex);
return (Evas_Preload_Pthread*) work;
return work;
}
on_error:
if (_evas_preload_thread_count == 0)
{
if (work->func_cancel)
work->func_cancel((void *) work->data);
if (work->func_cancel) work->func_cancel(work->data);
free(work);
}
return NULL;
@ -257,41 +244,39 @@ 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((void *) data);
func_end((void *) data);
func_heavy(data);
func_end(data);
return EINA_TRUE;
return NULL;
#endif
}
Eina_Bool
evas_preload_thread_cancel(Evas_Preload_Pthread *thread)
evas_preload_thread_cancel(Evas_Preload_Pthread_Worker *wk)
{
#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;
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;
}
_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;
}
LKU(_mutex);
/* Delay the destruction */
work = (Evas_Preload_Pthread_Worker *) thread;
work->cancel = EINA_TRUE;
wk->cancel = EINA_TRUE;
return EINA_FALSE;
#else
return EINA_TRUE;

View File

@ -374,7 +374,8 @@ 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 Evas_Preload_Pthread;
typedef struct _Evas_Preload_Pthread_Worker Evas_Preload_Pthread_Worker;
typedef struct _Evas_Preload_Pthread_Data Evas_Preload_Pthread_Data;
typedef struct _RGBA_Image_Loadopts RGBA_Image_Loadopts;
#ifdef BUILD_PIPE_RENDER
@ -529,8 +530,8 @@ struct _Image_Entry
const char *file;
const char *key;
Evas_Cache_Target *targets;
Evas_Preload_Pthread *preload;
Evas_Cache_Target *targets;
Evas_Preload_Pthread_Worker *preload;
time_t timestamp;
time_t laststat;

View File

@ -801,11 +801,12 @@ int evas_async_target_del(const void *target);
void _evas_preload_thread_init(void);
void _evas_preload_thread_shutdown(void);
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);
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);
void _evas_walk(Evas *e);
void _evas_unwalk(Evas *e);