#include <string.h>
#include <stdio.h>
+
+static win_threads_t __win_threads = NULL;
+
+static win_threads_t
+__win_threads_instance(void);
+
+static int
+__win_threads_attach(win_thread_t thread);
+
+static int
+__win_threads_detach(win_thread_t thread);
+
+static void
+__win_threads_free(void);
+
+static void
+__win_threads_lock(void);
+
+static void
+__win_threads_unlock(void);
+
+static win_thread_t
+__win_thread_self(void);
+
+static int
+__win_thread_key_attach(win_thread_t thread,win_thread_key_t key);
+
+static int
+__win_thread_key_detach(win_thread_t thread,win_thread_key_t key);
+
int
win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* param){
if(!*thread)
return 1;
+ (*thread)->keys = xbt_new0(s_win_thread_keys_t,1);
+
+ if(!((*thread)->keys)){
+ xbt_free(*thread);
+ return 1;
+ }
+
(*thread)->handle = CreateThread(NULL,NULL,start_routine,param,0,&((*thread)->id));
if(!((*thread)->handle)){
return 1;
}
+ __win_threads_attach(*thread);
+
return 0;
}
int
win_thread_exit(win_thread_t* thread,unsigned long exit_code)
{
- win_thread_t ___thread = *thread;
-
+ win_thread_key_t cur,next;
+ win_thread_t ___thread = *thread;
+
+ __win_threads_detach(*thread);
+
CloseHandle(___thread->handle);
- free(___thread);
+
+ cur = ___thread->keys->front;
+
+ while(cur){
+
+ next = cur->next;
+
+ if(cur->dstr_func){
+
+ (*(cur->dstr_func))(win_thread_getspecific(cur));
+ win_thread_key_delete(cur);
+
+ }
+
+ cur = next;
+ }
+
+ xbt_free(___thread->keys);
+ xbt_free(___thread);
___thread = NULL;
-
+
ExitThread(exit_code);
-
-
return 0;
}
-unsigned long
+win_thread_t
win_thread_self(void){
- return GetCurrentThreadId();
+ return __win_thread_self();
}
int
int
win_thread_mutex_unlock(win_thread_mutex_t* mutex){
- LeaveCriticalSection (&(*mutex)->lock);
+ LeaveCriticalSection (&((*mutex)->lock));
return 0;
}
/* lock the threads counter and increment it */
EnterCriticalSection (&((*cond)->waiters_count_lock));
(*cond)->waiters_count++;
- LeaveCriticalSection (&((*cond)->waiters_count_lock));
+ LeaveCriticalSection(&((*cond)->waiters_count_lock));
/* unlock the mutex associate with the condition */
- LeaveCriticalSection (&(*mutex)->lock);
+ LeaveCriticalSection(&(*mutex)->lock);
/* wait for a signal (broadcast or no) */
wait_result = WaitForMultipleObjects (2, (*cond)->events, FALSE, INFINITE);
/* it's the last waiter or it's a broadcast ? */
is_last_waiter = ((wait_result == WAIT_OBJECT_0 + BROADCAST - 1) && ((*cond)->waiters_count == 0));
- LeaveCriticalSection (&((*cond)->waiters_count_lock));
+ LeaveCriticalSection(&((*cond)->waiters_count_lock));
/* yes it's the last waiter or it's a broadcast
* only reset the manual event (the automatic event is reset in the WaitForMultipleObjects() function
EnterCriticalSection (&((*cond)->waiters_count_lock));
have_waiters = (*cond)->waiters_count > 0;
- LeaveCriticalSection (&((*cond)->waiters_count_lock));
+ LeaveCriticalSection(&((*cond)->waiters_count_lock));
if (have_waiters){
EnterCriticalSection (&((*cond)->waiters_count_lock));
have_waiters = (*cond)->waiters_count > 0;
- LeaveCriticalSection (&((*cond)->waiters_count_lock));
+ LeaveCriticalSection(&((*cond)->waiters_count_lock));
if (have_waiters)
SetEvent((*cond)->events[BROADCAST]);
}
+int
+win_thread_key_create(win_thread_key_t* key, pfn_key_dstr_func_t dstr_func)
+{
+ *key = xbt_new0(s_win_thread_key_t,1);
+
+ if(!(*key))
+ return 1;
+
+ if(__win_thread_key_attach(__win_thread_self(),*key){
+ xbt_free(*key);
+ *key = NULL;
+ return 1;
+ }
+
+ (*key)->value = TlsAlloc();
+ (*key)->dstr_func = dstr_func;
+
+ return 0;
+}
+
+int
+win_thread_key_delete(win_thread_key_t key)
+{
+ void* p;
+ int success;
+
+ if(!key)
+ return 1;
+
+ if(!TlsFree(key->value))
+ return 1;
+
+ success = __win_thread_key_detach(__win_thread_self(),key);
+
+ xbt_free(key);
+
+ return success;
+}
+
+int
+win_thread_setspecific(win_thread_key_t key, const void* p)
+{
+ if(!key)
+ return 1;
+
+ if(!TlsSetValue(key->key,(void*)p))
+ return 1;
+
+ return 0;
+}
+
+void*
+win_thread_getspecific(win_thread_key_t key)
+{
+ if(!key)
+ return NULL;
+
+ return TlsGetValue(key->value);
+}
+
+
+static win_threads_t
+__win_threads_instance(void){
+
+ if(!__win_threads){
+ __win_threads = xbt_new0(s_win_threads_t,1);
+
+ if(!__win_threads)
+ return NULL;
+
+ InitializeCriticalSection(&(__win_threads->lock));
+ }
+
+ return __win_threads;
+}
+
+static int
+__win_threads_attach(win_thread_t thread)
+{
+ win_thread_entry_t entry;
+ win_threads_t threads;
+
+ __win_threads_lock();
+
+ threads = __win_threads_instance();
+
+ if(!threads){
+ __win_threads_unlock();
+ return 1;
+ }
+
+
+ entry = xbt_new0(win_thread_entry_t,1);
+
+ if(!entry){
+ __win_threads_unlock();
+ return 1;
+ }
+
+ entry->thread = thread;
+
+ if(threads->front){
+ entry->next = threads->front;
+ threads->front->prev = entry;
+ }
+
+ threads->front = entry;
+ threads->size++;
+
+ __win_threads_unlock();
+ return 0;
+}
+
+static int
+__win_threads_detach(win_thread_t thread)
+{
+ win_thread_entry_t cur;
+ win_threads_t threads ;
+
+
+ __win_threads_lock();
+
+ threads = __win_threads_instance();
+
+ if(!threads){
+ __win_threads_unlock();
+ return 1;
+ }
+
+ cur = threads->front;
+
+ while(cur){
+
+ if(cur->thread == thread){
+
+ if(cur->next)
+ cur->next->prev = cur->prev;
+
+ if(cur->prev)
+ cur->prev->next = cur->next;
+
+ xbt_free(cur);
+
+ threads->size--;
+
+ if(!(threads->size))
+ __win_threads_free();
+ else
+ __win_threads_unlock();
+
+ return 0;
+ }
+
+ cur = cur->next;
+ }
+
+ __win_threads_unlock();
+ return 1;
+}
+
+static win_thread_t
+__win_thread_self(void)
+{
+ win_thread_entry_t cur;
+ win_threads_t threads ;
+ win_thread_t thread;
+ unsigned long thread_id;
+
+ __win_threads_lock();
+
+ thread_id = GetCurrentThreadId();
+
+ threads = __win_threads_instance();
+
+ if(!threads){
+ __win_threads_unlock();
+ return NULL;
+ }
+
+ cur = threads->front;
+
+ while(cur){
+
+ if(cur->thread->id == thread_id){
+
+ thread = cur->thread;
+ __win_threads_unlock();
+ return thread;
+ }
+
+ cur = cur->next;
+ }
+
+ __win_threads_unlock();
+ return NULL;
+}
+
+static void
+__win_threads_free(void)
+{
+ CRITICAL_SECTION lock;
+
+ if(__win_threads){
+ lock = __win_threads->lock;
+ free(__win_threads);
+ __win_threads = NULL;
+ LeaveCriticalSection(&lock);
+ DeleteCriticalSection(&lock);
+ }
+}
+
+static void
+__win_threads_lock(void)
+{
+ EnterCriticalSection(&(__win_threads->lock));
+}
+
+static void
+__win_threads_unlock(void)
+{
+ LeaveCriticalSection(&(__win_threads->lock));
+}
+
+static int
+__win_thread_key_attach(win_thread_t thread,win_thread_key_t key)
+{
+ win_thread_keys_t keys;
+
+ keys = thread->keys;
+
+ if(!keys)
+ return 1;
+
+
+ if(keys->front){
+ key->next = keys->front;
+ keys->front->prev = key;
+ }
+
+ keys->front = key;
+
+ return 0;
+}
+
+static int
+__win_thread_key_detach(win_thread_t thread,win_thread_key_t key)
+{
+ win_thread_key_t cur;
+ win_thread_keys_t keys ;
+
+ keys = thread->keys;
+
+ if(!keys)
+ return 1;
+
+ cur = keys->front;
+
+ while(cur){
+
+ if(cur == key){
+
+ if(cur->next)
+ cur->next->prev = cur->prev;
+
+ if(cur->prev)
+ cur->prev->next = cur->next;
+
+ return 0;
+ }
+
+ cur = cur->next;
+ }
+
+ return 1;
+}
+
+
+
+
/* type of function pointeur used */
typedef DWORD WINAPI (*pfn_start_routine_t)(void*);
+typedef struct s_win_thread_key s_win_thread_key_t,* win_thread_key_t;
+typedef struct s_win_thread_keys s_win_thread_keys_t,* win_thread_keys_t;
+
/*
* This structure represents a windows thread.
*/
typedef struct s_win_thread
{
HANDLE handle; /* the win thread handle */
- unsigned long id; /* the win thread id */
+ unsigned long id; /* the win thread id */
+ win_thread_keys_t keys;
}s_win_thread_t,* win_thread_t;
+struct s_win_thread_keys
+{
+ win_thread_key_t* keys;
+ win_thread_key_t front;
+ win_thread_key_t back;
+};
+
+typedef struct s_win_thread_entry
+{
+ HANDLE handle;
+ win_thread_t thread;
+ win_thread_t next;
+ win_thread_t prev;
+}s_win_thread_entry_t,win_thread_entry_t;
+
+typedef struct s_win_threads
+{
+ win_thread_entry_t* threads;
+ win_thread_entry_t front;
+ win_thread_entry_t back;
+ unsigned int size;
+ CRITICAL_SECTION lock;
+}s_win_threads_t,* win_threads_t;
+
+
/*
* This structure simulates a pthread cond.
*/
CRITICAL_SECTION waiters_count_lock;/* protect access to waiters_count */
}s_win_thread_cond_t,* win_thread_cond_t;
+
+/* type of pointer function used by the
+ * win_thread_key_create() function.
+ */
+typedef void (*pfn_key_dstr_func_t) (void*);
+
+/*
+ * This structure represents a windows key
+ */
+struct s_win_thread_key
+{
+ unsigned long value; /* the key value */
+ pfn_key_dstr_func_t dstr_func; /* the pointer to the destruction function */
+ win_thread_key_t next;
+ win_thread_key_t prev;
+};
+
+
/*
* This structure represents a windows mutext
* remark : only encapsulate the mutext handle.
/*
* Return the identifier of the current thread.
*/
-unsigned long
+win_thread_t
win_thread_self(void);
/*
void
win_thread_yield(void);
+
+/*
+ * windows thread key connected functions
+ */
+
+/*
+ * Create a windows thread key.
+ * @param key The pointer to the key to create.
+ * @param dstr_func The pointer to the cleanup function.
+ * @return If successful the function returns .Otherwise
+ * the function returns 1.
+ */
+int
+win_thread_key_create(win_thread_key_t* key, pfn_key_dstr_func_t dstr_func);
+/*
+ * Destroy a key.
+ * @param key The key to delete.
+ * @return If successful the function returns 0.
+ * Otherwise the function returns 1.
+ */
+int
+win_thread_key_delete(win_thread_key_t key);
+
+/*
+ * Update or set the value associated to a key.
+ * @param key The key concerned by the operation.
+ * @param value The value to set or update.
+ * @return If successful the function returns 0.
+ * Otherwise the function returns 1.
+ */
+int
+win_thread_setspecific(win_thread_key_t key, const void* p);
+
+/*
+ * Return the value associated to a key.
+ * @param key The key concerned by the operation.
+ * @return If successful the function returns the value.
+ * Otherwise the function returns NULL.
+ */
+void*
+win_thread_getspecific(win_thread_key_t key);
+
+
+
+
+
#ifdef __cplusplus
extern }
#endif