Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add some thread functions
authorcherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 8 Mar 2007 20:23:04 +0000 (20:23 +0000)
committercherierm <cherierm@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Thu, 8 Mar 2007 20:23:04 +0000 (20:23 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@3213 48e7efb5-ca39-0410-a469-dd3cf9ba447f

src/xbt/win_thread.c
src/xbt/win_thread.h

index 0e6e3c4..72d1ae8 100644 (file)
@@ -3,6 +3,36 @@
 #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){
 
@@ -11,6 +41,13 @@ win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* p
        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)){
@@ -19,28 +56,49 @@ win_thread_create(win_thread_t* thread,pfn_start_routine_t start_routine,void* p
                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
@@ -68,7 +126,7 @@ win_thread_mutex_lock(win_thread_mutex_t* mutex){
 int
 win_thread_mutex_unlock(win_thread_mutex_t* mutex){
 
-       LeaveCriticalSection (&(*mutex)->lock);
+       LeaveCriticalSection (&((*mutex)->lock));
        return 0;               
 }
 
@@ -133,11 +191,11 @@ win_thread_cond_wait(win_thread_cond_t* cond,win_thread_mutex_t* mutex){
         /* 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);
@@ -152,7 +210,7 @@ win_thread_cond_wait(win_thread_cond_t* cond,win_thread_mutex_t* mutex){
        /* 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
@@ -177,7 +235,7 @@ win_thread_cond_signal(win_thread_cond_t* cond)
 
        EnterCriticalSection (&((*cond)->waiters_count_lock));
        have_waiters = (*cond)->waiters_count > 0;
-       LeaveCriticalSection (&((*cond)->waiters_count_lock));
+       LeaveCriticalSection(&((*cond)->waiters_count_lock));
        
        if (have_waiters){
                
@@ -196,7 +254,7 @@ win_thread_cond_broadcast(win_thread_cond_t* cond)
 
        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]);
@@ -232,3 +290,282 @@ win_thread_yield(void)
 }
 
 
+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;
+}
+
+
+
+
index f6c47e6..536d2b2 100644 (file)
@@ -19,15 +19,44 @@ extern "C" {
 /* 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.
  */
@@ -47,6 +76,24 @@ typedef struct s_win_thread_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.
@@ -83,7 +130,7 @@ win_thread_exit(win_thread_t* thread,unsigned long exit_code);
 /*
  * Return the identifier of the current thread.
  */
-unsigned long
+win_thread_t
 win_thread_self(void);
 
 /*
@@ -183,6 +230,52 @@ win_thread_cond_destroy(win_thread_cond_t* cond);
 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