forked from enlightenment/efl
parent
4b14ea628c
commit
903bbfba82
|
@ -48,3 +48,7 @@
|
||||||
2012-10-19 Patryk Kaczmarek
|
2012-10-19 Patryk Kaczmarek
|
||||||
|
|
||||||
* eina_stringshare_add_length return NULL when func args are wrong.
|
* eina_stringshare_add_length return NULL when func args are wrong.
|
||||||
|
|
||||||
|
2012-10-19 Cedric Bail
|
||||||
|
|
||||||
|
* Add eina_thread API.
|
||||||
|
|
1
NEWS
1
NEWS
|
@ -9,6 +9,7 @@ Additions:
|
||||||
* Add DOCTYPE children parsing in eina_simple_xml
|
* Add DOCTYPE children parsing in eina_simple_xml
|
||||||
* Add eina_barrier thread API
|
* Add eina_barrier thread API
|
||||||
* Add eina_tmpstr_add() and eina_tmpstr_del()
|
* Add eina_tmpstr_add() and eina_tmpstr_del()
|
||||||
|
* Add eina_thread API
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
* Single EFL tree now covring all EFL library components.
|
* Single EFL tree now covring all EFL library components.
|
||||||
|
|
|
@ -225,6 +225,7 @@ extern "C" {
|
||||||
#include "eina_cpu.h"
|
#include "eina_cpu.h"
|
||||||
#include "eina_sched.h"
|
#include "eina_sched.h"
|
||||||
#include "eina_tiler.h"
|
#include "eina_tiler.h"
|
||||||
|
#include "eina_thread.h"
|
||||||
#include "eina_hamster.h"
|
#include "eina_hamster.h"
|
||||||
#include "eina_matrixsparse.h"
|
#include "eina_matrixsparse.h"
|
||||||
#include "eina_str.h"
|
#include "eina_str.h"
|
||||||
|
|
|
@ -59,6 +59,7 @@ eina_inline_rbtree.x \
|
||||||
eina_inline_mempool.x \
|
eina_inline_mempool.x \
|
||||||
eina_inline_rectangle.x \
|
eina_inline_rectangle.x \
|
||||||
eina_inline_trash.x \
|
eina_inline_trash.x \
|
||||||
|
eina_thread.h \
|
||||||
eina_trash.h \
|
eina_trash.h \
|
||||||
eina_iterator.h \
|
eina_iterator.h \
|
||||||
eina_main.h \
|
eina_main.h \
|
||||||
|
@ -145,6 +146,7 @@ eina_strbuf.c \
|
||||||
eina_strbuf_common.c \
|
eina_strbuf_common.c \
|
||||||
eina_stringshare.c \
|
eina_stringshare.c \
|
||||||
eina_tiler.c \
|
eina_tiler.c \
|
||||||
|
eina_thread.c \
|
||||||
eina_unicode.c \
|
eina_unicode.c \
|
||||||
eina_ustrbuf.c \
|
eina_ustrbuf.c \
|
||||||
eina_ustringshare.c \
|
eina_ustringshare.c \
|
||||||
|
|
|
@ -157,6 +157,7 @@ EAPI Eina_Inlist *_eina_tracking = NULL;
|
||||||
S(prefix);
|
S(prefix);
|
||||||
S(value);
|
S(value);
|
||||||
S(tmpstr);
|
S(tmpstr);
|
||||||
|
S(thread);
|
||||||
/* no model for now
|
/* no model for now
|
||||||
S(model);
|
S(model);
|
||||||
*/
|
*/
|
||||||
|
@ -198,6 +199,7 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
|
||||||
S(prefix),
|
S(prefix),
|
||||||
S(value),
|
S(value),
|
||||||
S(tmpstr),
|
S(tmpstr),
|
||||||
|
S(thread)
|
||||||
/* no model for now
|
/* no model for now
|
||||||
S(model)
|
S(model)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
/* EINA - EFL data type library
|
||||||
|
* Copyright (C) 2012 Cedric Bail
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library;
|
||||||
|
* if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_EVIL
|
||||||
|
# include <Evil.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "eina_config.h"
|
||||||
|
#include "eina_thread.h"
|
||||||
|
#include "eina_sched.h"
|
||||||
|
|
||||||
|
#ifdef EINA_HAVE_THREADS
|
||||||
|
# ifdef _WIN32_WCE
|
||||||
|
|
||||||
|
# elif defined(_WIN32)
|
||||||
|
|
||||||
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
# include <windows.h>
|
||||||
|
# undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
|
||||||
|
struct _Eina_Thread_Win32
|
||||||
|
{
|
||||||
|
HANDLE thread;
|
||||||
|
Eina_Thread_Cb func;
|
||||||
|
void *data;
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
Eina_Thread index;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: For the moment Eina_Thread is considered not
|
||||||
|
thread safe, wondering if it's worth it */
|
||||||
|
static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */
|
||||||
|
static Eina_List *_thread_pool = NULL;
|
||||||
|
static Eina_List *_thread_running = NULL;
|
||||||
|
|
||||||
|
static Eina_Thread_Win32 *
|
||||||
|
_eina_thread_win32_find(Eina_Thread index)
|
||||||
|
{
|
||||||
|
Eina_Thread_Win32 *tw;
|
||||||
|
Eina_List *l;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(_thread_running, l, tw)
|
||||||
|
if (tw->index == index)
|
||||||
|
return tw;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Thread
|
||||||
|
_eina_thread_win32_self(void)
|
||||||
|
{
|
||||||
|
HANDLE t;
|
||||||
|
|
||||||
|
t = GetCurrentThread();
|
||||||
|
EINA_LIST_FOREACH(_thread_running, l, tw)
|
||||||
|
if (tw->thread == t)
|
||||||
|
return tw->index;
|
||||||
|
|
||||||
|
/* We assume main loop == 0 on Windows */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_thread_win32_equal(Eina_Thread t1, Eina_Thread t2)
|
||||||
|
{
|
||||||
|
if (t1 == t2) return EINA_TRUE;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI
|
||||||
|
_eina_thread_win32_cb(LPVOID lpParam)
|
||||||
|
{
|
||||||
|
Eina_Thread_Win32 *tw = lpParam;
|
||||||
|
|
||||||
|
tw->ret = tw->func(tw->data, tw->index);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_thread_win32_create(Eina_Thread *t,
|
||||||
|
Eina_Thread_Cb func,
|
||||||
|
const void *data)
|
||||||
|
{
|
||||||
|
Eina_Thread_Win32 *tw;
|
||||||
|
Eina_List *l;
|
||||||
|
|
||||||
|
tw = eina_list_data_get(_thread_pool);
|
||||||
|
_thread_pool = eina_list_remove_list(_thread_pool, _thread_pool);
|
||||||
|
|
||||||
|
if (!tw)
|
||||||
|
{
|
||||||
|
tw = malloc(sizeof (Eina_Thread_Win32));
|
||||||
|
if (!tw) goto on_error;
|
||||||
|
|
||||||
|
do {
|
||||||
|
tw->index = _current_index++;
|
||||||
|
} while (tw->index == 0); /* prevent having a "false" main loop */
|
||||||
|
}
|
||||||
|
|
||||||
|
tw->func = f;
|
||||||
|
tw->data = d;
|
||||||
|
|
||||||
|
tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
|
||||||
|
if (!tw->thread) goto on_error;
|
||||||
|
|
||||||
|
_thread_running = eina_list_append(_thread_running, tw);
|
||||||
|
|
||||||
|
*t = tw->index;
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
on_error:
|
||||||
|
_thread_pool = eina_list_append(_thread_pool, tw);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
_eina_thread_win32_join(Eina_Thread t)
|
||||||
|
{
|
||||||
|
Eina_Thread_Win32 *tw;
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
tw = _eina_thread_win32_find(index);
|
||||||
|
if (!tw) return NULL;
|
||||||
|
|
||||||
|
WaitForSingleObject(tw->thread, INFINITE);
|
||||||
|
CloseHandle(tw->thread);
|
||||||
|
|
||||||
|
ret = tw->ret;
|
||||||
|
|
||||||
|
tw->ret = NULL;
|
||||||
|
tw->thread = NULL;
|
||||||
|
tw->func = NULL;
|
||||||
|
tw->data = NULL;
|
||||||
|
|
||||||
|
_thread_running = eina_list_remove(_thread_running, tw);
|
||||||
|
_thread_pool = eina_list_append(_thread_pool, _thread_pool);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define PHE(x, y) _eina_thread_win32_equal(x, y)
|
||||||
|
# define PHS() _eina_thread_win32_self()
|
||||||
|
# define PHC(x, f, d) _eina_thread_win32_create(x, f, d)
|
||||||
|
# define PHJ(x) _eina_thread_win32_join(x)
|
||||||
|
|
||||||
|
# else
|
||||||
|
# include <pthread.h>
|
||||||
|
|
||||||
|
# ifdef __linux__
|
||||||
|
# include <sched.h>
|
||||||
|
# include <sys/resource.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <sys/syscall.h>
|
||||||
|
# include <errno.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static void *
|
||||||
|
_eina_thread_join(Eina_Thread t)
|
||||||
|
{
|
||||||
|
void *ret = NULL;
|
||||||
|
|
||||||
|
if (!pthread_join(t, &ret))
|
||||||
|
return ret;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define PHE(x, y) pthread_equal(x, y)
|
||||||
|
# define PHS() pthread_self()
|
||||||
|
# define PHC(x, f, d) pthread_create(x, NULL, (void*) f, d)
|
||||||
|
# define PHJ(x) _eina_thread_join(x)
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# error "Not supported any more"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _Eina_Thread_Call Eina_Thread_Call;
|
||||||
|
struct _Eina_Thread_Call
|
||||||
|
{
|
||||||
|
Eina_Thread_Cb func;
|
||||||
|
const void *data;
|
||||||
|
|
||||||
|
Eina_Thread_Priority prio;
|
||||||
|
Eina_Bool affinity;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "eina_thread.h"
|
||||||
|
|
||||||
|
static void *
|
||||||
|
_eina_internal_call(void *context)
|
||||||
|
{
|
||||||
|
Eina_Thread_Call *c = context;
|
||||||
|
void *r;
|
||||||
|
|
||||||
|
if (c->prio == EINA_THREAD_BACKGROUND ||
|
||||||
|
c->prio == EINA_THREAD_IDLE)
|
||||||
|
eina_sched_prio_drop();
|
||||||
|
|
||||||
|
/* FIXME: set priority and affinity */
|
||||||
|
r = c->func((void*) c->data, eina_thread_self());
|
||||||
|
|
||||||
|
free(c);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Thread
|
||||||
|
eina_thread_self(void)
|
||||||
|
{
|
||||||
|
return PHS();
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
eina_thread_equal(Eina_Thread t1, Eina_Thread t2)
|
||||||
|
{
|
||||||
|
return !!(PHE(t1, t2));
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
eina_thread_create(Eina_Thread *t,
|
||||||
|
Eina_Thread_Priority prio, Eina_Bool affinity,
|
||||||
|
Eina_Thread_Cb func, const void *data)
|
||||||
|
{
|
||||||
|
Eina_Thread_Call *c;
|
||||||
|
|
||||||
|
c = malloc(sizeof (Eina_Thread_Call));
|
||||||
|
if (!c) return EINA_FALSE;
|
||||||
|
|
||||||
|
c->func = func;
|
||||||
|
c->data = data;
|
||||||
|
c->prio = prio;
|
||||||
|
c->affinity = affinity;
|
||||||
|
|
||||||
|
if (PHC(t, _eina_internal_call, c) == 0)
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
free(c);
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void *
|
||||||
|
eina_thread_join(Eina_Thread t)
|
||||||
|
{
|
||||||
|
return PHJ(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eina_thread_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eina_thread_shutdown(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* EINA - EFL data type library
|
||||||
|
* Copyright (C) 2012 Cedric Bail
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library;
|
||||||
|
* if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EINA_THREAD_H_
|
||||||
|
#define EINA_THREAD_H_
|
||||||
|
|
||||||
|
#include "eina_config.h"
|
||||||
|
#include "eina_types.h"
|
||||||
|
#include "eina_error.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup Eina_Tools_Group Tools
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup Eina_Thread_Group Thread
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef EINA_HAVE_THREADS
|
||||||
|
# ifdef _WIN32_WCE
|
||||||
|
|
||||||
|
typedef unsigned long int Eina_Thread;
|
||||||
|
|
||||||
|
# elif defined(_WIN32)
|
||||||
|
|
||||||
|
typedef unsigned long int Eina_Thread;
|
||||||
|
|
||||||
|
# else
|
||||||
|
# include <pthread.h>
|
||||||
|
|
||||||
|
typedef pthread_t Eina_Thread;
|
||||||
|
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# error "Build without thread is not supported any more"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void *(*Eina_Thread_Cb)(void *data, Eina_Thread t);
|
||||||
|
|
||||||
|
typedef enum _Eina_Thread_Priority
|
||||||
|
{
|
||||||
|
EINA_THREAD_URGENT,
|
||||||
|
EINA_THREAD_NORMAL,
|
||||||
|
EINA_THREAD_BACKGROUND,
|
||||||
|
EINA_THREAD_IDLE
|
||||||
|
} Eina_Thread_Priority;
|
||||||
|
|
||||||
|
EAPI Eina_Thread eina_thread_self(void);
|
||||||
|
EAPI Eina_Bool eina_thread_equal(Eina_Thread t1, Eina_Thread t2);
|
||||||
|
EAPI Eina_Bool eina_thread_create(Eina_Thread *t,
|
||||||
|
Eina_Thread_Priority prio, Eina_Bool affinity,
|
||||||
|
Eina_Thread_Cb func, const void *data);
|
||||||
|
EAPI void *eina_thread_join(Eina_Thread t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue