libuv学习笔记(23)

来源:互联网 发布:恶意百度点击软件 编辑:程序博客网 时间:2024/06/16 21:41

libuv学习笔记(23)

线程相关数据结构与函数(1)

数据结构

typedef HANDLE uv_thread_t;//就是句柄
typedef struct {//线程局部变量使用  DWORD tls_index;} uv_key_t;
typedef struct uv_once_s {//libuv用此结构保证某一函数只执行一次  unsigned char ran;  HANDLE event;} uv_once_t;
typedef CRITICAL_SECTION uv_mutex_t;//通过临界区实现互斥量

线程相关API

创建线程

int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {  struct thread_ctx* ctx;  int err;  HANDLE thread;  ctx = uv__malloc(sizeof(*ctx));//将在uv__thread_start中释放  if (ctx == NULL)    return UV_ENOMEM;  ctx->entry = entry;  ctx->arg = arg;  //创建线程  thread = (HANDLE) _beginthreadex(NULL,                                   0,                                   uv__thread_start,                                   ctx,                                   CREATE_SUSPENDED,                                   NULL);  if (thread == NULL) {    err = errno;    uv__free(ctx);  } else {    err = 0;    *tid = thread;    ctx->self = thread;    ResumeThread(thread);  }  switch (err) {    case 0:      return 0;    case EACCES:      return UV_EACCES;    case EAGAIN:      return UV_EAGAIN;    case EINVAL:      return UV_EINVAL;  }  return UV_EIO;}

新线程调用的函数

static UINT __stdcall uv__thread_start(void* arg) {  struct thread_ctx *ctx_p;  struct thread_ctx ctx;  ctx_p = arg;  ctx = *ctx_p;  uv__free(ctx_p);//释放  //调用uv_key_create初始化TLS  key   uv__current_thread_key  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);  //将本线程的句柄存入线程本地存储,通过uv__current_thread_key标识  uv_key_set(&uv__current_thread_key, (void*) ctx.self);  ctx.entry(ctx.arg);//调用真正的任务函数  return 0;}

获取线程句柄,需要在线程中调用,该线程通过uv_thread_create创建

uv_thread_t uv_thread_self(void) {  uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key);  return (uv_thread_t) uv_key_get(&uv__current_thread_key);}

等待线程执行完成

int uv_thread_join(uv_thread_t *tid) {  if (WaitForSingleObject(*tid, INFINITE))    return uv_translate_sys_error(GetLastError());  else {    CloseHandle(*tid);    *tid = 0;    return 0;  }}

线程本地存储

创建TLS key,注意线程本地存储大小有限,本函数可能会失败,无法创建更多的本地存储

int uv_key_create(uv_key_t* key) {  key->tls_index = TlsAlloc();  if (key->tls_index == TLS_OUT_OF_INDEXES)    return UV_ENOMEM;  return 0;}

释放线程本地存储变量

void uv_key_delete(uv_key_t* key) {  if (TlsFree(key->tls_index) == FALSE)    abort();  key->tls_index = TLS_OUT_OF_INDEXES;}

获取线程本地存储变量

void* uv_key_get(uv_key_t* key) {  void* value;  value = TlsGetValue(key->tls_index);//调用API  if (value == NULL)    if (GetLastError() != ERROR_SUCCESS)      abort();  return value;}

设置线程本地存储变量

void uv_key_set(uv_key_t* key, void* value) {  if (TlsSetValue(key->tls_index, value) == FALSE)//TLS API    abort();}

只运行一次的方法,通过uv_once_t标识

void uv_once(uv_once_t* guard, void (*callback)(void)) {  if (guard->ran) {//如果正在运行,返回    return;  }  uv__once_inner(guard, callback);}
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {  DWORD result;  HANDLE existing_event, created_event;  created_event = CreateEvent(NULL, 1, 0, NULL);//创建事件句柄  if (created_event == 0) {    uv_fatal_error(GetLastError(), "CreateEvent");  }  //原子改变变量的值,并返回原来的值  existing_event = InterlockedCompareExchangePointer(&guard->event,                                                     created_event,                                                     NULL);  //如果existing_event 原来为空,表示是第一次执行  if (existing_event == NULL) {    callback();//调用回调    result = SetEvent(created_event);//改变event状态    assert(result);    guard->ran = 1;//已经运行,修改表计量  } else {    //并不是第一次,说明有线程通过相同的uv_once_t在本线程之前调用了uv_once    CloseHandle(created_event);    //等待直到先运行的线程调用回调函数执行完成    result = WaitForSingleObject(existing_event, INFINITE);    assert(result == WAIT_OBJECT_0);  }}

互斥锁相关函数

初始化

int uv_mutex_init(uv_mutex_t* mutex) {  InitializeCriticalSection(mutex);//初始化临界区  return 0;}

释放互斥锁

void uv_mutex_destroy(uv_mutex_t* mutex) {  DeleteCriticalSection(mutex);//释放临界区}

锁定

void uv_mutex_lock(uv_mutex_t* mutex) {  EnterCriticalSection(mutex);//进入临界区}

尝试锁定

int uv_mutex_trylock(uv_mutex_t* mutex) {  if (TryEnterCriticalSection(mutex))//尝试进入临界区    return 0;  else    return UV_EBUSY;}

解锁

void uv_mutex_unlock(uv_mutex_t* mutex) {  LeaveCriticalSection(mutex);//离开临界区}
0 0
原创粉丝点击