voiduv_once(uv_once_t* guard,void(*callback)(void)){/* Fast case - avoid WaitForSingleObject. *///避免线程处于等待状态if(guard->ran){return;}uv__once_inner(guard, callback);}
1
2
3
4
5
6
7
8
uv__once_inner
staticvoiduv__once_inner(uv_once_t* guard,void(*callback)(void)){
DWORD result;
HANDLE existing_event, created_event;//函数将创建一个手动重置事件对象,该对象需要使用 ResetEvent 函数将事件状态设置为非对齐状态
created_event =CreateEvent(NULL,1,0,NULL);//创建或打开命名或未命名的事件对象//函数调用成功,则返回事件对象的句柄,//如果在函数调用之前存在命名事件对象,该函数将返回现有对象的句柄if(created_event ==0){/* Could fail in a low-memory situation? *///在内存不足的情况下可能失败?uv_fatal_error(GetLastError(),"CreateEvent");}//比较两个值(参数1和参数3) 如果参数1和参数3相等,那么就把参数2赋予参数1,//返回值为参数1未调用方法之前的值,该方法为原子操作,如果参数1和参数3不相等,那么//参数1是不会进行修改的
existing_event =InterlockedCompareExchangePointer(&guard->event,
created_event,NULL);//表示参数1在进入InterlockedCompareExchangePointer方法之前就是空的,所以我们赢了if(existing_event ==NULL){/* We won the race */callback();//初始化系统级的环境
result =SetEvent(created_event);//将指定的事件对象设置为有信号状态(有标记)//由于是手动重置事件,所以该事件会一直保持//有标记状态,直至调用ResetEvent才结束。//在libuv中,该event永远有标记不会被重置assert(result);
guard->ran =1;//该标记位只初始化一次,即该方法只会调用一次,//永远不会被重置}else{/* We lost the race. Destroy the event we created and wait for the existing
* one to become signaled. *///我们输了,销毁我们创建的事件,等待现有事件发出信号CloseHandle(created_event);//等待事件对象处于无信号状态或者超时间隔已过,即此处可能有多个线程处于等待状态
result =WaitForSingleObject(existing_event, INFINITE);assert(result == WAIT_OBJECT_0);}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
uv_init
staticvoiduv_init(void){/* Tell Windows that we will handle critical errors. *///告诉Windows我们将处理关键错误//SEM_FAILCRITICALERRORS:系统不显示严重错误处理程序消息框。相反,系统会将错误发送到调用进程。//为了防止错误模式对话框挂起应用程序。//SEM_NOGPFAULTERRORBOX: 系统不显示Windows 错误报告对话框。//SEM_NOOPENFILEERRORBOX:OpenFile 函数在找不到文件时不显示消息框。相反,错误将返回到调用方。SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
SEM_NOOPENFILEERRORBOX);/* Tell the CRT to not exit the application when an invalid parameter is
* passed. The main issue is that invalid FDs will trigger this behavior.
*///告诉CRT在传递无效参数时不要退出应用程序,主要是无效的FDs将触发此行为//CRT:Microsoft开发的C/C++ Runtime Library#if!defined(__MINGW32__)|| __MSVCRT_VERSION__ >=0x800_set_invalid_parameter_handler(uv__crt_invalid_parameter_handler);#endif/* We also need to setup our debug report handler because some CRT
* functions (eg _get_osfhandle) raise an assert when called with invalid
* FDs even though they return the proper error code in the release build.
*///我们还需要设置调试报告处理程序,因为一些CRT函数(如_get_osfhandle)在使用无效//FDs调用时会引发断言,即使它们在发布版本中返回正确的错误代码#ifdefined(_DEBUG)&&(defined(_MSC_VER)||defined(__MINGW64_VERSION_MAJOR))_CrtSetReportHook(uv__crt_dbg_report_handler);#endif/* Initialize tracking of all uv loops *///初始化一个互斥变量,用于解决同步互斥问题uv__loops_init();/* Fetch winapi function pointers. This must be done first because other
* initialization code might need these function pointers to be loaded.
*///获取WindowsAPI,赋值我们自定义的函数指针,这个过程必须一开始就初始化完毕,因为其他初始化//代码可能需要加载这些函数指针。实际上就是通过dll动态链接库加载相应的模块uv_winapi_init();/* Initialize winsock *///加载Windows socket环境uv_winsock_init();/* Initialize FS *///FS:file systemuv_fs_init();/* Initialize signal stuff *///初始化信号量uv_signals_init();/* Initialize console *///初始化控制台相关uv_console_init();/* Initialize utilities *///检测系统性能计数器的频率uv__util_init();/* Initialize system wakeup detection *///初始化系统唤醒检测(主机开机关机生命周期)uv__init_detect_system_wakeup();}
/*
* One-time initialization code for functionality defined in util.c.
*/voiduv__util_init(void){
LARGE_INTEGER perf_frequency;/* Initialize process title access mutex. */InitializeCriticalSection(&process_title_lock);//创建一个互斥量/* Retrieve high-resolution timer frequency
* and precompute its reciprocal.
*///检索性能计数器的频率。性能计数器的频率在系统启动时固定,在所有处理器中保持一致。//因此,只需在应用程序初始化时查询频率,并且可以缓存结果。//CPU上也有一个计数器,以机器人的clock为单位,可以通过rdtsc读取,//而不用中断,因此其精度与系统时间相当。//精度:计算机获取硬件支持,精度比较高,可以通过它来判断其它时间函数的精度范围。if(QueryPerformanceFrequency(&perf_frequency)){
hrtime_frequency_ = perf_frequency.QuadPart;}else{uv_fatal_error(GetLastError(),"QueryPerformanceFrequency");}}