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
|
@ -496,13 +496,19 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
static inline Eina_Bool
|
||||||
eina_tls_new(Eina_TLS *key)
|
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_FALSE;
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Eina_Bool
|
||||||
|
eina_tls_new(Eina_TLS *key)
|
||||||
|
{
|
||||||
|
return eina_tls_cb_new(key, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
eina_tls_free(Eina_TLS key)
|
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_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
|
static inline Eina_Bool
|
||||||
|
@ -481,16 +484,31 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Eina_Bool
|
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)
|
if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
if (delete_cb)
|
||||||
|
{
|
||||||
|
if (!_eina_thread_tls_cb_register(*key, delete_cb))
|
||||||
|
{
|
||||||
|
TlsFree(key);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Eina_Bool
|
||||||
|
eina_tls_new(Eina_TLS *key)
|
||||||
|
{
|
||||||
|
return eina_tls_cb_new(key, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
eina_tls_free(Eina_TLS key)
|
eina_tls_free(Eina_TLS key)
|
||||||
{
|
{
|
||||||
|
_eina_thread_tls_cb_unregister(key);
|
||||||
TlsFree(key);
|
TlsFree(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,6 +523,7 @@ eina_tls_set(Eina_TLS key, const void *data)
|
||||||
{
|
{
|
||||||
if (TlsSetValue(key, (LPVOID)data) == 0)
|
if (TlsSetValue(key, (LPVOID)data) == 0)
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
_eina_thread_tls_key_add(key);
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
EAPI extern Eina_Bool _threads_activated;
|
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 HANDLE Eina_Lock;
|
||||||
typedef Eina_Lock Eina_Spinlock;
|
typedef Eina_Lock Eina_Spinlock;
|
||||||
|
@ -151,17 +154,32 @@ eina_rwlock_release(Eina_RWLock *mutex)
|
||||||
return eina_lock_release(mutex);
|
return eina_lock_release(mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static inline Eina_Bool
|
||||||
eina_tls_new(Eina_TLS *key)
|
eina_tls_new(Eina_TLS *key)
|
||||||
{
|
{
|
||||||
if (TlsAlloc() == TLS_OUT_OF_INDEXES)
|
return eina_tls_cb_new(key, NULL);
|
||||||
return EINA_FALSE;
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
eina_tls_free(Eina_TLS key)
|
eina_tls_free(Eina_TLS key)
|
||||||
{
|
{
|
||||||
|
_eina_thread_tls_cb_unregister(key);
|
||||||
TlsFree(key);
|
TlsFree(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +194,7 @@ eina_tls_set(Eina_TLS key, const void *data)
|
||||||
{
|
{
|
||||||
if (TlsSetValue(key, (LPVOID)data) == 0)
|
if (TlsSetValue(key, (LPVOID)data) == 0)
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
_eina_thread_tls_key_add(key);
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@ typedef enum
|
||||||
EINA_LOCK_DEADLOCK
|
EINA_LOCK_DEADLOCK
|
||||||
} Eina_Lock_Result;
|
} Eina_Lock_Result;
|
||||||
|
|
||||||
|
typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
|
||||||
|
|
||||||
#ifdef _WIN32_WCE
|
#ifdef _WIN32_WCE
|
||||||
# include "eina_inline_lock_wince.x"
|
# include "eina_inline_lock_wince.x"
|
||||||
#elif defined(_WIN32)
|
#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) */
|
/** @relates static Eina_Bool eina_tls_new(pthread_key_t *key) */
|
||||||
static inline Eina_Bool eina_tls_new(Eina_TLS *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) */
|
/** @relates static void eina_tls_free(pthread_key_t key) */
|
||||||
static inline void eina_tls_free(Eina_TLS key);
|
static inline void eina_tls_free(Eina_TLS key);
|
||||||
/** @relates static void eina_tls_get(pthread_key_t key) */
|
/** @relates static void eina_tls_get(pthread_key_t key) */
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "eina_sched.h"
|
#include "eina_sched.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include "eina_list.h"
|
# include "eina_list.h"
|
||||||
|
# include "eina_lock.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
||||||
|
@ -38,6 +39,12 @@
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# undef WIN32_LEAN_AND_MEAN
|
# 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;
|
typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
|
||||||
struct _Eina_Thread_Win32
|
struct _Eina_Thread_Win32
|
||||||
{
|
{
|
||||||
|
@ -45,6 +52,7 @@ struct _Eina_Thread_Win32
|
||||||
void *(*func)(void *data);
|
void *(*func)(void *data);
|
||||||
void *data;
|
void *data;
|
||||||
void *ret;
|
void *ret;
|
||||||
|
Eina_List *tls_keys;
|
||||||
|
|
||||||
Eina_Thread index;
|
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 unsigned long int _current_index = 1; /* start from one as the main loop == 0 */
|
||||||
static Eina_List *_thread_pool = NULL;
|
static Eina_List *_thread_pool = NULL;
|
||||||
static Eina_List *_thread_running = 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 *
|
static Eina_Thread_Win32 *
|
||||||
_eina_thread_win32_find(Eina_Thread index)
|
_eina_thread_win32_find(Eina_Thread index)
|
||||||
|
@ -123,6 +206,7 @@ _eina_thread_create(Eina_Thread *t,
|
||||||
|
|
||||||
tw->func = func;
|
tw->func = func;
|
||||||
tw->data = (void *)data;
|
tw->data = (void *)data;
|
||||||
|
tw->tls_keys = NULL;
|
||||||
|
|
||||||
tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
|
tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
|
||||||
if (!tw->thread) goto on_error;
|
if (!tw->thread) goto on_error;
|
||||||
|
@ -159,6 +243,7 @@ _eina_thread_join(Eina_Thread t)
|
||||||
tw->thread = NULL;
|
tw->thread = NULL;
|
||||||
tw->func = NULL;
|
tw->func = NULL;
|
||||||
tw->data = NULL;
|
tw->data = NULL;
|
||||||
|
_eina_thread_tls_keys_clean(tw);
|
||||||
|
|
||||||
_thread_running = eina_list_remove(_thread_running, tw);
|
_thread_running = eina_list_remove(_thread_running, tw);
|
||||||
_thread_pool = eina_list_append(_thread_pool, _thread_pool);
|
_thread_pool = eina_list_append(_thread_pool, _thread_pool);
|
||||||
|
|
|
@ -77,33 +77,57 @@ START_TEST(eina_test_spinlock)
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
static Eina_TLS key;
|
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 *
|
static void *
|
||||||
_eina_test_tls_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
|
_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));
|
ptr = eina_tls_get(key);
|
||||||
fail_if(eina_tls_get(key) != &mystack);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(eina_test_tls)
|
START_TEST(eina_test_tls)
|
||||||
{
|
{
|
||||||
unsigned int ft = 42;
|
|
||||||
|
|
||||||
fail_if(!eina_init());
|
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));
|
fail_if(!eina_thread_create(&thread, EINA_THREAD_NORMAL, 0, _eina_test_tls_thread, NULL));
|
||||||
|
|
||||||
eina_thread_join(thread);
|
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);
|
eina_tls_free(key);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue