summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJérémy Zurcher <jeremy@asynk.ch>2014-01-23 14:50:08 +0900
committerCedric BAIL <cedric.bail@samsung.com>2014-01-23 14:50:08 +0900
commit316dc52d2f758bba2263cd25b940d1e4457910fd (patch)
tree39e2cf97040ceb144a04987b9c972f0f0c35dbad /src
parent1d7d554348f76645734772b48d83ae63d8ca6de8 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/lib/eina/eina_inline_lock_posix.x12
-rw-r--r--src/lib/eina/eina_inline_lock_win32.x21
-rw-r--r--src/lib/eina/eina_inline_lock_wince.x25
-rw-r--r--src/lib/eina/eina_lock.h4
-rw-r--r--src/lib/eina/eina_thread.c85
-rw-r--r--src/tests/eina/eina_test_lock.c40
6 files changed, 172 insertions, 15 deletions
diff --git a/src/lib/eina/eina_inline_lock_posix.x b/src/lib/eina/eina_inline_lock_posix.x
index 5270f467fb..b9136fcef5 100644
--- a/src/lib/eina/eina_inline_lock_posix.x
+++ b/src/lib/eina/eina_inline_lock_posix.x
@@ -495,14 +495,20 @@ eina_rwlock_release(Eina_RWLock *mutex)
495 return EINA_LOCK_SUCCEED; 495 return EINA_LOCK_SUCCEED;
496} 496}
497 497
498static inline Eina_Bool 498static inline Eina_Bool
499eina_tls_new(Eina_TLS *key) 499eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
500{ 500{
501 if (pthread_key_create(key, NULL) != 0) 501 if (pthread_key_create(key, delete_cb) != 0)
502 return EINA_FALSE; 502 return EINA_FALSE;
503 return EINA_TRUE; 503 return EINA_TRUE;
504} 504}
505 505
506static inline Eina_Bool
507eina_tls_new(Eina_TLS *key)
508{
509 return eina_tls_cb_new(key, NULL);
510}
511
506static inline void 512static inline void
507eina_tls_free(Eina_TLS key) 513eina_tls_free(Eina_TLS key)
508{ 514{
diff --git a/src/lib/eina/eina_inline_lock_win32.x b/src/lib/eina/eina_inline_lock_win32.x
index 6feb60d649..3123ad6d9b 100644
--- a/src/lib/eina/eina_inline_lock_win32.x
+++ b/src/lib/eina/eina_inline_lock_win32.x
@@ -71,6 +71,9 @@ struct _Eina_RWLock
71 71
72 72
73EAPI extern Eina_Bool _eina_threads_activated; 73EAPI extern Eina_Bool _eina_threads_activated;
74EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb);
75EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key);
76EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key);
74 77
75 78
76static inline Eina_Bool 79static inline Eina_Bool
@@ -481,16 +484,31 @@ eina_rwlock_release(Eina_RWLock *mutex)
481} 484}
482 485
483static inline Eina_Bool 486static inline Eina_Bool
484eina_tls_new(Eina_TLS *key) 487eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
485{ 488{
486 if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES) 489 if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
487 return EINA_FALSE; 490 return EINA_FALSE;
491 if (delete_cb)
492 {
493 if (!_eina_thread_tls_cb_register(*key, delete_cb))
494 {
495 TlsFree(key);
496 return EINA_FALSE;
497 }
498 }
488 return EINA_TRUE; 499 return EINA_TRUE;
489} 500}
490 501
502static inline Eina_Bool
503eina_tls_new(Eina_TLS *key)
504{
505 return eina_tls_cb_new(key, NULL);
506}
507
491static inline void 508static inline void
492eina_tls_free(Eina_TLS key) 509eina_tls_free(Eina_TLS key)
493{ 510{
511 _eina_thread_tls_cb_unregister(key);
494 TlsFree(key); 512 TlsFree(key);
495} 513}
496 514
@@ -505,6 +523,7 @@ eina_tls_set(Eina_TLS key, const void *data)
505{ 523{
506 if (TlsSetValue(key, (LPVOID)data) == 0) 524 if (TlsSetValue(key, (LPVOID)data) == 0)
507 return EINA_FALSE; 525 return EINA_FALSE;
526 _eina_thread_tls_key_add(key);
508 return EINA_TRUE; 527 return EINA_TRUE;
509} 528}
510 529
diff --git a/src/lib/eina/eina_inline_lock_wince.x b/src/lib/eina/eina_inline_lock_wince.x
index 3b732568da..3d96a84533 100644
--- a/src/lib/eina/eina_inline_lock_wince.x
+++ b/src/lib/eina/eina_inline_lock_wince.x
@@ -26,6 +26,9 @@
26#undef WIN32_LEAN_AND_MEAN 26#undef WIN32_LEAN_AND_MEAN
27 27
28EAPI extern Eina_Bool _threads_activated; 28EAPI extern Eina_Bool _threads_activated;
29EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb);
30EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key);
31EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key);
29 32
30typedef HANDLE Eina_Lock; 33typedef HANDLE Eina_Lock;
31typedef Eina_Lock Eina_Spinlock; 34typedef Eina_Lock Eina_Spinlock;
@@ -151,17 +154,32 @@ eina_rwlock_release(Eina_RWLock *mutex)
151 return eina_lock_release(mutex); 154 return eina_lock_release(mutex);
152} 155}
153 156
154static inline Eina_Bool 157static inline Eina_Bool
155eina_tls_new(Eina_TLS *key) 158eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
156{ 159{
157 if (TlsAlloc() == TLS_OUT_OF_INDEXES) 160 if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
158 return EINA_FALSE; 161 return EINA_FALSE;
162 if (delete_cb)
163 {
164 if (!_eina_thread_tls_cb_register(*key, delete_cb))
165 {
166 TlsFree(key);
167 return EINA_FALSE;
168 }
169 }
159 return EINA_TRUE; 170 return EINA_TRUE;
160} 171}
161 172
173static inline Eina_Bool
174eina_tls_new(Eina_TLS *key)
175{
176 return eina_tls_cb_new(key, NULL);
177}
178
162static inline void 179static inline void
163eina_tls_free(Eina_TLS key) 180eina_tls_free(Eina_TLS key)
164{ 181{
182 _eina_thread_tls_cb_unregister(key);
165 TlsFree(key); 183 TlsFree(key);
166} 184}
167 185
@@ -176,6 +194,7 @@ eina_tls_set(Eina_TLS key, const void *data)
176{ 194{
177 if (TlsSetValue(key, (LPVOID)data) == 0) 195 if (TlsSetValue(key, (LPVOID)data) == 0)
178 return EINA_FALSE; 196 return EINA_FALSE;
197 _eina_thread_tls_key_add(key);
179 return EINA_TRUE; 198 return EINA_TRUE;
180} 199}
181 200
diff --git a/src/lib/eina/eina_lock.h b/src/lib/eina/eina_lock.h
index b0afa4193f..ac0c8b1bb3 100644
--- a/src/lib/eina/eina_lock.h
+++ b/src/lib/eina/eina_lock.h
@@ -42,6 +42,8 @@ typedef enum
42 EINA_LOCK_DEADLOCK 42 EINA_LOCK_DEADLOCK
43} Eina_Lock_Result; 43} Eina_Lock_Result;
44 44
45typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
46
45#ifdef _WIN32_WCE 47#ifdef _WIN32_WCE
46# include "eina_inline_lock_wince.x" 48# include "eina_inline_lock_wince.x"
47#elif defined(_WIN32) 49#elif defined(_WIN32)
@@ -91,6 +93,8 @@ static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
91 93
92/** @relates static Eina_Bool eina_tls_new(pthread_key_t *key) */ 94/** @relates static Eina_Bool eina_tls_new(pthread_key_t *key) */
93static inline Eina_Bool eina_tls_new(Eina_TLS *key); 95static inline Eina_Bool eina_tls_new(Eina_TLS *key);
96/** @relates static Eina_Bool eina_tls_cb_new(pthread_key_t *key, Eina_TLS_Delete_Cb delete_cb) */
97static inline Eina_Bool eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb);
94/** @relates static void eina_tls_free(pthread_key_t key) */ 98/** @relates static void eina_tls_free(pthread_key_t key) */
95static inline void eina_tls_free(Eina_TLS key); 99static inline void eina_tls_free(Eina_TLS key);
96/** @relates static void eina_tls_get(pthread_key_t key) */ 100/** @relates static void eina_tls_get(pthread_key_t key) */
diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c
index b4e07e7c37..5ba6c57e69 100644
--- a/src/lib/eina/eina_thread.c
+++ b/src/lib/eina/eina_thread.c
@@ -27,6 +27,7 @@
27#include "eina_sched.h" 27#include "eina_sched.h"
28#ifdef _WIN32 28#ifdef _WIN32
29# include "eina_list.h" 29# include "eina_list.h"
30# include "eina_lock.h"
30#endif 31#endif
31 32
32/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ 33/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
@@ -38,6 +39,12 @@
38# include <windows.h> 39# include <windows.h>
39# undef WIN32_LEAN_AND_MEAN 40# undef WIN32_LEAN_AND_MEAN
40 41
42typedef struct _Eina_TLS_Cbs_Win32 Eina_TLS_Cbs_Win32;
43struct _Eina_TLS_Cbs_Win32
44{
45 Eina_TLS key;
46 Eina_TLS_Delete_Cb cb;
47};
41typedef struct _Eina_Thread_Win32 Eina_Thread_Win32; 48typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
42struct _Eina_Thread_Win32 49struct _Eina_Thread_Win32
43{ 50{
@@ -45,6 +52,7 @@ struct _Eina_Thread_Win32
45 void *(*func)(void *data); 52 void *(*func)(void *data);
46 void *data; 53 void *data;
47 void *ret; 54 void *ret;
55 Eina_List *tls_keys;
48 56
49 Eina_Thread index; 57 Eina_Thread index;
50}; 58};
@@ -54,6 +62,81 @@ struct _Eina_Thread_Win32
54static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */ 62static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */
55static Eina_List *_thread_pool = NULL; 63static Eina_List *_thread_pool = NULL;
56static Eina_List *_thread_running = NULL; 64static Eina_List *_thread_running = NULL;
65static Eina_List *_tls_keys_cbs = NULL;
66
67static inline Eina_TLS_Cbs_Win32 *
68_eina_thread_tls_cb_find(Eina_TLS key)
69{
70 Eina_TLS_Cbs_Win32 *cb;
71 Eina_List *l;
72
73 EINA_LIST_FOREACH(_tls_keys_cbs, l, cb)
74 if (cb->key == key)
75 return cb;
76
77 return NULL;
78}
79
80static inline void
81_eina_thread_tls_keys_clean(Eina_Thread_Win32 *tw)
82{
83 void *data;
84 Eina_TLS_Cbs_Win32 *cb;
85
86 EINA_LIST_FREE(tw->tls_keys, data)
87 {
88 Eina_TLS key = data;
89 cb = _eina_thread_tls_cb_find(key);
90 if (cb)
91 cb->cb(eina_tls_get(key));
92 }
93 tw->tls_keys = NULL;
94}
95
96EAPI Eina_Bool
97_eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb)
98{
99 Eina_TLS_Cbs_Win32 *tls_cb = malloc(sizeof(Eina_TLS_Cbs_Win32));
100 if (!cb) return EINA_FALSE;
101
102 tls_cb->key = key;
103 tls_cb->cb = cb;
104 _tls_keys_cbs = eina_list_append(_tls_keys_cbs, tls_cb);
105
106 return EINA_TRUE;
107}
108
109EAPI Eina_Bool
110_eina_thread_tls_cb_unregister(Eina_TLS key)
111{
112 Eina_TLS_Cbs_Win32 *cb = _eina_thread_tls_cb_find(key);
113 if (!cb) return EINA_FALSE;
114
115 _tls_keys_cbs = eina_list_remove(_tls_keys_cbs, cb);
116 free(cb);
117
118 return EINA_TRUE;
119}
120
121EAPI Eina_Bool
122_eina_thread_tls_key_add(Eina_TLS key)
123{
124 HANDLE t;
125 Eina_Thread_Win32 *tw;
126 Eina_List *l;
127
128 t = GetCurrentThread();
129 EINA_LIST_FOREACH(_thread_running, l, tw)
130 if (tw->thread == t)
131 {
132 void *data = key;
133 if (!eina_list_data_find(tw->tls_keys, data))
134 tw->tls_keys = eina_list_append(tw->tls_keys, data);
135 return EINA_TRUE;
136 }
137
138 return EINA_FALSE;
139}
57 140
58static Eina_Thread_Win32 * 141static Eina_Thread_Win32 *
59_eina_thread_win32_find(Eina_Thread index) 142_eina_thread_win32_find(Eina_Thread index)
@@ -123,6 +206,7 @@ _eina_thread_create(Eina_Thread *t,
123 206
124 tw->func = func; 207 tw->func = func;
125 tw->data = (void *)data; 208 tw->data = (void *)data;
209 tw->tls_keys = NULL;
126 210
127 tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL); 211 tw->thread = CreateThread(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
128 if (!tw->thread) goto on_error; 212 if (!tw->thread) goto on_error;
@@ -159,6 +243,7 @@ _eina_thread_join(Eina_Thread t)
159 tw->thread = NULL; 243 tw->thread = NULL;
160 tw->func = NULL; 244 tw->func = NULL;
161 tw->data = NULL; 245 tw->data = NULL;
246 _eina_thread_tls_keys_clean(tw);
162 247
163 _thread_running = eina_list_remove(_thread_running, tw); 248 _thread_running = eina_list_remove(_thread_running, tw);
164 _thread_pool = eina_list_append(_thread_pool, _thread_pool); 249 _thread_pool = eina_list_append(_thread_pool, _thread_pool);
diff --git a/src/tests/eina/eina_test_lock.c b/src/tests/eina/eina_test_lock.c
index 9bac3041b8..7c6626eaa7 100644
--- a/src/tests/eina/eina_test_lock.c
+++ b/src/tests/eina/eina_test_lock.c
@@ -77,33 +77,57 @@ START_TEST(eina_test_spinlock)
77END_TEST 77END_TEST
78 78
79static Eina_TLS key; 79static Eina_TLS key;
80static int _eina_tls_free_count = 0;
81
82static void *
83_eina_test_tls_alloc(int v)
84{
85 int *ptr = malloc(sizeof(int));
86 *ptr = v;
87
88 return ptr;
89}
90
91static void
92_eina_test_tls_free(void *ptr)
93{
94 _eina_tls_free_count++;
95 free(ptr);
96}
80 97
81static void * 98static void *
82_eina_test_tls_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED) 99_eina_test_tls_thread(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
83{ 100{
84 unsigned int mystack = 21; 101 int *ptr;
102
103 ptr = eina_tls_get(key);
104 fail_if(eina_tls_get(key) != NULL);
85 105
86 fail_if(!eina_tls_set(key, &mystack)); 106 fail_if(!eina_tls_set(key, _eina_test_tls_alloc(24)));
87 fail_if(eina_tls_get(key) != &mystack); 107
108 ptr = eina_tls_get(key);
109 fail_if(eina_tls_get(key) == NULL);
110 fail_if(*ptr != 24);
88 111
89 return NULL; 112 return NULL;
90} 113}
91 114
92START_TEST(eina_test_tls) 115START_TEST(eina_test_tls)
93{ 116{
94 unsigned int ft = 42;
95
96 fail_if(!eina_init()); 117 fail_if(!eina_init());
97 118
98 fail_if(!eina_tls_new(&key)); 119 fail_if(!eina_tls_cb_new(&key, _eina_test_tls_free));
99 120
100 fail_if(!eina_tls_set(key, &ft)); 121 fail_if(!eina_tls_set(key, _eina_test_tls_alloc(42)));
101 122
102 fail_if(!eina_thread_create(&thread, EINA_THREAD_NORMAL, 0, _eina_test_tls_thread, NULL)); 123 fail_if(!eina_thread_create(&thread, EINA_THREAD_NORMAL, 0, _eina_test_tls_thread, NULL));
103 124
104 eina_thread_join(thread); 125 eina_thread_join(thread);
126 fail_if(_eina_tls_free_count != 1);
105 127
106 fail_if(eina_tls_get(key) != &ft); 128 int *ptr = eina_tls_get(key);
129 fail_if(eina_tls_get(key) == NULL);
130 fail_if(*ptr != 42);
107 131
108 eina_tls_free(key); 132 eina_tls_free(key);
109 133