| 
					
				 | 
			
			
				@@ -31,7 +31,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/* Posix implementation for gpr threads. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Windows implementation for gpr threads. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/port_platform.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -40,47 +40,81 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <windows.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/thd.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-struct thd_arg { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if defined(_MSC_VER) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define thread_local __declspec(thread) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#elif defined(__GNUC__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define thread_local __thread 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#error "Unknown compiler - please file a bug report" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+struct thd_info { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void (*body)(void *arg); /* body of a thread */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   void *arg;               /* argument to a thread */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  HANDLE join_event;       /* if joinable, the join event */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int joinable;            /* true if not detached */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static thread_local struct thd_info *g_thd_info; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Destroys a thread info */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static destroy_thread(struct thd_info *t) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (t->joinable) CloseHandle(t->join_event); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(t); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* Body of every thread started via gpr_thd_new. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static DWORD WINAPI thread_body(void *v) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  struct thd_arg a = *(struct thd_arg *)v; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_free(v); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  (*a.body)(a.arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  g_thd_info = (struct thd_info *)v; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  g_thd_info->body(g_thd_info->arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (g_thd_info->joinable) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    BOOL ret = SetEvent(g_thd_info->join_event); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(ret); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    destroy_thread(g_thd_info); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 const gpr_thd_options *options) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   HANDLE handle; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  DWORD thread_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  struct thd_arg *a = gpr_malloc(sizeof(*a)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  a->body = thd_body; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  a->arg = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  struct thd_info *info = gpr_malloc(sizeof(*info)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  info->body = thd_body; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  info->arg = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   *t = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  handle = CreateThread(NULL, 64 * 1024, thread_body, a, 0, &thread_id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (gpr_thd_options_is_joinable(options)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    info->joinable = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    info->join_event = CreateEvent(NULL, FALSE, FALSE, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (info->join_event == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_free(info); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    info->joinable = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  handle = CreateThread(NULL, 64 * 1024, thread_body, info, 0, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (handle == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_free(a); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    destroy_thread(info); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    CloseHandle(handle); /* threads are "detached" */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    *t = (gpr_thd_id)info; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    CloseHandle(handle); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  *t = (gpr_thd_id)thread_id; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return handle != NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-gpr_thd_options gpr_thd_options_default(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_thd_options options; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  memset(&options, 0, sizeof(options)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return options; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+gpr_thd_id gpr_thd_currentid(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return (gpr_thd_id)g_thd_info; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-gpr_thd_id gpr_thd_currentid(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return (gpr_thd_id)GetCurrentThreadId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void gpr_thd_join(gpr_thd_id t) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  struct thd_info *info = (struct thd_info *)t; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  DWORD ret = WaitForSingleObject(info->join_event, INFINITE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPR_ASSERT(ret == WAIT_OBJECT_0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  destroy_thread(info); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif /* GPR_WIN32 */ 
			 |