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);//离开临界区
}