parent
4b14ea628c
commit
903bbfba82
7 changed files with 371 additions and 0 deletions
@ -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