forked from enlightenment/efl
eina_tls: add eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
Summary: delete_cb is called at thread exit for each Eina_TLS keys used by the thread Details: posix: pthread_key_create(key, delete_cb); does it win32/wince: eina_tls_free/new un/registers key&&cb into a static eina_list. eina_tls_set add the key to an eina_list in Eina_Thread_Win3. this list is cleared and callbacks are called in _eina_thread_join() Test Plan: win32/wince has to be tested, I have no setup to do it. Reviewers: cedric CC: cedric Differential Revision: https://phab.enlightenment.org/D489
This commit is contained in:
parent
1d7d554348
commit
316dc52d2f
|
@ -495,14 +495,20 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
|||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
static inline Eina_Bool
|
||||
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
if (pthread_key_create(key, NULL) != 0)
|
||||
if (pthread_key_create(key, delete_cb) != 0)
|
||||
return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
{
|
||||
return eina_tls_cb_new(key, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
|
|
|
@ -71,6 +71,9 @@ struct _Eina_RWLock
|
|||
|
||||
|
||||
EAPI extern Eina_Bool _eina_threads_activated;
|
||||
EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb);
|
||||
EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key);
|
||||
EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key);
|
||||
|
||||
|
||||
static inline Eina_Bool
|
||||
|
@ -481,16 +484,31 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
|||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
|
||||
return EINA_FALSE;
|
||||
if (delete_cb)
|
||||
{
|
||||
if (!_eina_thread_tls_cb_register(*key, delete_cb))
|
||||
{
|
||||
TlsFree(key);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
{
|
||||
return eina_tls_cb_new(key, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
_eina_thread_tls_cb_unregister(key);
|
||||
TlsFree(key);
|
||||
}
|
||||
|
||||
|
@ -505,6 +523,7 @@ eina_tls_set(Eina_TLS key, const void *data)
|
|||
{
|
||||
if (TlsSetValue(key, (LPVOID)data) == 0)
|
||||
return EINA_FALSE;
|
||||
_eina_thread_tls_key_add(key);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#undef WIN32_LEAN_AND_MEAN
|
||||
|
||||
EAPI extern Eina_Bool _threads_activated;
|
||||
EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb);
|
||||
EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key);
|
||||
EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key);
|
||||
|
||||
typedef HANDLE Eina_Lock;
|
||||
typedef Eina_Lock Eina_Spinlock;
|
||||
|
@ -151,17 +154,32 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
|||
return eina_lock_release(mutex);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
static inline Eina_Bool
|
||||
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
|
||||
return EINA_FALSE;
|
||||
if (delete_cb)
|
||||
{
|
||||
if (!_eina_thread_tls_cb_register(*key, delete_cb))
|
||||
{
|
||||
TlsFree(key);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
{
|
||||
if (TlsAlloc() == TLS_OUT_OF_INDEXES)
|
||||
return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
return eina_tls_cb_new(key, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
_eina_thread_tls_cb_unregister(key);
|
||||
TlsFree(key);
|
||||
}
|
||||
|
||||
|
@ -176,6 +194,7 @@ eina_tls_set(Eina_TLS key, const void *data)
|
|||
{
|
||||
if (TlsSetValue(key, (LPVOID)data) == 0)
|
||||
return EINA_FALSE;
|
||||
_eina_thread_tls_key_add(key);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ typedef enum
|
|||
EINA_LOCK_DEADLOCK
|
||||
} Eina_Lock_Result;
|
||||
|
||||
typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
# include "eina_inline_lock_wince.x"
|
||||
#elif defined(_WIN32)
|
||||
|
@ -91,6 +93,8 @@ static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
|
|||
|
||||
/** @relates static Eina_Bool eina_tls_new(pthread_key_t *key) */
|
||||
static inline Eina_Bool eina_tls_new(Eina_TLS *key);
|
||||
/** @relates static Eina_Bool eina_tls_cb_new(pthread_key_t *key, Eina_TLS_Delete_Cb delete_cb) */
|
||||
static inline Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb);
|
||||
/** @relates static void eina_tls_free(pthread_key_t key) */
|
||||
static inline void eina_tls_free(Eina_TLS key);
|
||||
/** @relates static void eina_tls_get(pthread_key_t key) */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "eina_sched.h"
|
||||
#ifdef _WIN32
|
||||
# include "eina_list.h"
|
||||
# include "eina_lock.h"
|
||||
#endif
|
||||
|
||||
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
||||
|
@ -38,6 +39,12 @@
|
|||
# include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
|
||||
typedef struct _Eina_TLS_Cbs_Win32 Eina_TLS_Cbs_Win32;
|
||||
struct _Eina_TLS_Cbs_Win32
|
||||
{
|
||||
Eina_TLS key;
|
||||
Eina_TLS_Delete_Cb cb;
|
||||
};
|
||||
typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
|
||||
struct _Eina_Thread_Win32
|
||||
{
|
||||
|
@ -45,6 +52,7 @@ struct _Eina_Thread_Win32
|
|||
void *(*func)(void *data);
|
||||
void *data;
|
||||
void *ret;
|
||||
Eina_List *tls_keys;
|
||||
|
||||
Eina_Thread index;
|
||||
};
|
||||
|
@ -54,6 +62,81 @@ struct _Eina_Thread_Win32
|
|||
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_List *_tls_keys_cbs = NULL;
|
||||
|
||||
static inline Eina_TLS_Cbs_Win32 *
|
||||
_eina_thread_tls_cb_find(Eina_TLS key)
|
||||
{
|
||||
Eina_TLS_Cbs_Win32 *cb;
|
||||
Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(_tls_keys_cbs, l, cb)
|
||||
if (cb->key == key)
|
||||
return cb;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_thread_tls_keys_clean(Eina_Thread_Win32 *tw)
|
||||
{
|
||||
void *data;
|
||||
Eina_TLS_Cbs_Win32 *cb;
|
||||
|
||||
EINA_LIST_FREE(tw->tls_keys, data)
|
||||
{
|
||||
Eina_TLS key = data;
|
||||
cb = _eina_thread_tls_cb_find(key);
|
||||
if (cb)
|
||||
cb->cb(eina_tls_get(key));
|
||||
}
|
||||
tw->tls_keys = NULL;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb)
|
||||
{
|
||||
Eina_TLS_Cbs_Win32 *tls_cb = malloc(sizeof(Eina_TLS_Cbs_Win32));
|
||||
if (!cb) return EINA_FALSE;
|
||||
|
||||
tls_cb->key = key;
|
||||
tls_cb->cb = cb;
|
||||
_tls_keys_cbs = eina_list_append(_tls_keys_cbs, tls_cb);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_thread_tls_cb_unregister(Eina_TLS key)
|
||||
{
|
||||
Eina_TLS_Cbs_Win32 *cb = _eina_thread_tls_cb_find(key);
|
||||
if (!cb) return EINA_FALSE;
|
||||
|
||||
_tls_keys_cbs = eina_list_remove(_tls_keys_cbs, cb);
|
||||
free(cb);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_thread_tls_key_add(Eina_TLS key)
|
||||
{
|
||||
HANDLE t;
|
||||
Eina_Thread_Win32 *tw;
|
||||
Eina_List *l;
|
||||
|
||||
t = GetCurrentThread();
|
||||
EINA_LIST_FOREACH(_thread_running, l, tw)
|
||||
if (tw->thread == t)
|
||||
{
|
||||
void *data = key;
|
||||
if (!eina_list_data_find(tw->tls_keys, data))
|
||||
tw->tls_keys = eina_list_append(tw->tls_keys, data);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Thread_Win32 *
|
||||
_eina_thread_win32_find(Eina_Thread index)
|
||||
|
@ -123,6 +206,7 @@ _eina_thread_create(Eina_Thread *t,
|
|||
|
||||
tw->func = func;
|
||||
tw->data = (void *)data;
|
||||
tw->tls_keys = NULL;
|
||||
|
||||
tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
|
||||
if (!tw->thread) goto on_error;
|
||||
|
@ -159,6 +243,7 @@ _eina_thread_join(Eina_Thread t)
|
|||
tw->thread = NULL;
|
||||
tw->func = NULL;
|
||||
tw->data = NULL;
|
||||
_eina_thread_tls_keys_clean(tw);
|
||||
|
||||
_thread_running = eina_list_remove(_thread_running, tw);
|
||||
_thread_pool = eina_list_append(_thread_pool, _thread_pool);
|
||||
|
|
|
@ -77,33 +77,57 @@ START_TEST(eina_test_spinlock)
|
|||
END_TEST
|
||||
|
||||
static Eina_TLS key;
|
||||
static int _eina_tls_free_count = 0;
|
||||
|
||||
static void *
|
||||
_eina_test_tls_alloc(int v)
|
||||
{
|
||||
int *ptr = malloc(sizeof(int));
|
||||
*ptr = v;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void
|
||||
_eina_test_tls_free(void *ptr)
|
||||
{
|
||||
_eina_tls_free_count++;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void *
|
||||
_eina_test_tls_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
|
||||
{
|
||||
unsigned int mystack = 21;
|
||||
int *ptr;
|
||||
|
||||
fail_if(!eina_tls_set(key, &mystack));
|
||||
fail_if(eina_tls_get(key) != &mystack);
|
||||
ptr = eina_tls_get(key);
|
||||
fail_if(eina_tls_get(key) != NULL);
|
||||
|
||||
fail_if(!eina_tls_set(key, _eina_test_tls_alloc(24)));
|
||||
|
||||
ptr = eina_tls_get(key);
|
||||
fail_if(eina_tls_get(key) == NULL);
|
||||
fail_if(*ptr != 24);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
START_TEST(eina_test_tls)
|
||||
{
|
||||
unsigned int ft = 42;
|
||||
|
||||
fail_if(!eina_init());
|
||||
|
||||
fail_if(!eina_tls_new(&key));
|
||||
fail_if(!eina_tls_cb_new(&key, _eina_test_tls_free));
|
||||
|
||||
fail_if(!eina_tls_set(key, &ft));
|
||||
fail_if(!eina_tls_set(key, _eina_test_tls_alloc(42)));
|
||||
|
||||
fail_if(!eina_thread_create(&thread, EINA_THREAD_NORMAL, 0, _eina_test_tls_thread, NULL));
|
||||
|
||||
eina_thread_join(thread);
|
||||
fail_if(_eina_tls_free_count != 1);
|
||||
|
||||
fail_if(eina_tls_get(key) != &ft);
|
||||
int *ptr = eina_tls_get(key);
|
||||
fail_if(eina_tls_get(key) == NULL);
|
||||
fail_if(*ptr != 42);
|
||||
|
||||
eina_tls_free(key);
|
||||
|
||||
|
|
Loading…
Reference in New Issue