libuv学习笔记(23)

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值