|  | @@ -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 */
 |