#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;
_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;
};
{
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;
-
- if (pthread_join(pth->thread, (void **) &p) != 0)
- return ;
+ Evas_Preload_Pthread_Data *pth = data;
+ Evas_Preload_Pthread_Data *p = NULL;
- _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;
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
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
}
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);
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;
#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
}
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