lots of cleanups... actually tested! :)

SVN revision: 52030
This commit is contained in:
Carsten Haitzler 2010-09-09 07:08:10 +00:00
parent 679d566fde
commit c4ee82f6a7
1 changed files with 61 additions and 93 deletions

View File

@ -14,7 +14,10 @@
#include "evas_private.h"
#include "Evas.h"
static int _threads_max = 0;
#ifdef BUILD_ASYNC_PRELOAD
typedef struct _Evas_Preload_Pthread_Worker Evas_Preload_Pthread_Worker;
typedef struct _Evas_Preload_Pthread_Data Evas_Preload_Pthread_Data;
@ -25,9 +28,7 @@ struct _Evas_Preload_Pthread_Worker
_evas_preload_pthread_func func_heavy;
_evas_preload_pthread_func func_end;
_evas_preload_pthread_func func_cancel;
const void *data;
void *data;
Eina_Bool cancel : 1;
};
@ -35,89 +36,73 @@ struct _Evas_Preload_Pthread_Data
{
pthread_t thread;
};
#endif
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 = NULL;
static int _threads_count = 0;
static Eina_List *_workers = 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 *p;
Evas_Preload_Pthread_Data *pth = data;
Evas_Preload_Pthread_Data *p = NULL;
if (pthread_join(pth->thread, (void **) &p) != 0)
return ;
_evas_preload_thread = eina_list_remove(_evas_preload_thread, pth);
if (pthread_join(pth->thread, (void **)&p) != 0) free(p);
}
static void
_evas_preload_thread_done(void *target __UNUSED__, Evas_Callback_Type type __UNUSED__, void *event_info)
{
Evas_Preload_Pthread_Worker *work;
work = event_info;
Evas_Preload_Pthread_Worker *work = event_info;
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 (!_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(_workers);
_workers = eina_list_remove_list(_workers, _workers);
LKU(_mutex);
work->func_heavy((void *) work->data);
if (work->func_heavy) work->func_heavy(work->data);
evas_async_events_put(pth, 0, work, _evas_preload_thread_done);
}
LKL(_mutex);
if (_evas_preload_thread_data)
if (_workers)
{
LKU(_mutex);
goto on_error;
}
_evas_preload_thread_count--;
_threads_count--;
LKU(_mutex);
work = malloc(sizeof (Evas_Preload_Pthread_Worker));
// dummy worker to wake things up
work = malloc(sizeof(Evas_Preload_Pthread_Worker));
if (!work) return NULL;
work->data = pth;
@ -135,9 +120,8 @@ _evas_preload_thread_worker(Evas_Preload_Pthread_Data *pth)
void
_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;
_threads_max = eina_cpu_count();
if (_threads_max <= 0) _threads_max = 1;
}
void
@ -153,22 +137,13 @@ _evas_preload_thread_shutdown(void)
LKL(_mutex);
EINA_LIST_FREE(_evas_preload_thread_data, work)
EINA_LIST_FREE(_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);
}
#endif
}
@ -182,7 +157,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 +168,24 @@ 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);
_workers = eina_list_append(_workers, work);
if (_evas_preload_thread_count == _evas_preload_thread_count_max)
if (_threads_count == _threads_max)
{
pthread_mutex_unlock(&_mutex);
return (Evas_Preload_Pthread*) work;
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;
if (pthread_create(&pth->thread, NULL, (void *) _evas_preload_thread_worker, pth) == 0)
pth = malloc(sizeof(Evas_Preload_Pthread_Data));
if (!pth) goto on_error;
if (pthread_create(&pth->thread, NULL, _evas_preload_thread_worker, pth) == 0)
{
#ifdef __linux__
struct sched_param param;
@ -239,27 +213,25 @@ evas_preload_thread_run(void (*func_heavy) (void *data),
#endif
LKL(_mutex);
_evas_preload_thread_count++;
_threads_count++;
LKU(_mutex);
return (Evas_Preload_Pthread*) work;
return (Evas_Preload_Pthread*)work;
}
on_error:
if (_evas_preload_thread_count == 0)
if (_threads_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;
#else
/*
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.
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((void *)data);
func_end((void *)data);
return EINA_TRUE;
#endif
}
@ -272,25 +244,21 @@ evas_preload_thread_cancel(Evas_Preload_Pthread *thread)
Eina_List *l;
LKL(_mutex);
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;
}
EINA_LIST_FOREACH(_workers, l, work)
{
if (work == (Evas_Preload_Pthread_Worker *)thread)
{
_workers = eina_list_remove_list(_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 = (Evas_Preload_Pthread_Worker *)thread;
work->cancel = EINA_TRUE;
return EINA_FALSE;
#else