0%

向 Node.js 的底层再走一步

关于 Node.js 的异步编程之前已经稍微了解过了,再来继续深入研究一下用来支持它异步能力的底层事件库 —— Libuv。

这个标志还是很霸气的,也象征了这个库简单粗暴又高效的特点。


先扔两段代码:

单线程异步:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : libuv thread test
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#include "uv.h"

using namespace std;

uv_loop_t *loop;
uv_async_t async[5];
int wait[5] = {0, 1, 1, 2, 2};

void update_wait(int index)
{
wait[index]--;
if (wait[index] == 0)
uv_async_send(&async[index]);
}

void f0(uv_async_t *handle)
{
uv_thread_t id = uv_thread_self();
cout << "f0 run in " << id << endl;
update_wait(1);
uv_close((uv_handle_t*)&async[0], NULL);
}

void f1(uv_async_t *handle)
{
uv_thread_t id = uv_thread_self();
cout << "f1 run in " << id << endl;
update_wait(2);
update_wait(3);
update_wait(4);
uv_close((uv_handle_t*)&async[1], NULL);
}

void f2(uv_async_t *handle)
{
uv_thread_t id = uv_thread_self();
cout << "f2 run in " << id << endl;
update_wait(3);
uv_close((uv_handle_t*)&async[2], NULL);
}

void f3(uv_async_t *handle)
{
uv_thread_t id = uv_thread_self();
cout << "f3 run in " << id << endl;
update_wait(4);
uv_close((uv_handle_t*)&async[3], NULL);
}

void f4(uv_async_t *handle)
{
uv_thread_t id = uv_thread_self();
cout << "f4 run in " << id << endl;
uv_close((uv_handle_t*)&async[4], NULL);
}

int main()
{
cout << "Test Start" << endl;

uv_thread_t id = uv_thread_self();
cout << "Thread " << id << endl;

loop = uv_default_loop();
uv_async_init(loop, &async[0], f0);
uv_async_init(loop, &async[1], f1);
uv_async_init(loop, &async[2], f2);
uv_async_init(loop, &async[3], f3);
uv_async_init(loop, &async[4], f4);

uv_async_send(&async[0]);

uv_run(loop, UV_RUN_DEFAULT);

cout << "Loop End" << endl;

return 0;
}

多线程(queue_work 自带线程池)异步:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : libuv thread test
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#include "uv.h"

using namespace std;

uv_loop_t *loop;
uv_async_t async[5];
int wait[5] = {0, 1, 1, 2, 2};

void update_wait(int index)
{
wait[index]--;
if (wait[index] == 0)
uv_async_send(&async[index]);
}

void f0(uv_work_t *req)
{
uv_thread_t id = uv_thread_self();
cout << "f0 run in " << id << endl;
update_wait(1);
uv_close((uv_handle_t*)&async[0], NULL);
}

void f1(uv_work_t *req)
{
uv_thread_t id = uv_thread_self();
cout << "f1 run in " << id << endl;
update_wait(2);
update_wait(3);
update_wait(4);
uv_close((uv_handle_t*)&async[1], NULL);
}

void f2(uv_work_t *req)
{
uv_thread_t id = uv_thread_self();
cout << "f2 run in " << id << endl;
update_wait(3);
uv_close((uv_handle_t*)&async[2], NULL);
}

void f3(uv_work_t *req)
{
uv_thread_t id = uv_thread_self();
cout << "f3 run in " << id << endl;
update_wait(4);
uv_close((uv_handle_t*)&async[3], NULL);
}

void f4(uv_work_t *req)
{
uv_thread_t id = uv_thread_self();
cout << "f4 run in " << id << endl;
uv_close((uv_handle_t*)&async[4], NULL);
}

void after(uv_work_t *req, int status) {

}

void new_run(uv_async_t *handle)
{
cout << "New Run" << endl;
uv_work_t *req = new uv_work_t();
uv_queue_work(loop, req, (uv_work_cb)(uv_work_cb*)handle->data, after);
}

int main()
{
cout << "Test Start" << endl;

uv_thread_t id = uv_thread_self();
cout << "Thread " << id << endl;

loop = uv_default_loop();

async[0].data = (void*)&f0;
async[1].data = (void*)&f1;
async[2].data = (void*)&f2;
async[3].data = (void*)&f3;
async[4].data = (void*)&f4;

uv_async_init(loop, &async[0], new_run);
uv_async_init(loop, &async[1], new_run);
uv_async_init(loop, &async[2], new_run);
uv_async_init(loop, &async[3], new_run);
uv_async_init(loop, &async[4], new_run);

uv_async_send(&async[0]);

uv_run(loop, UV_RUN_DEFAULT);

cout << "Loop End" << endl;

int aaaaaa;
cin >> aaaaaa;

return 0;
}

To be continued …