Skip to content

Commit d59d6e6

Browse files
committed
doc: add code samples from uvbook (unadapted)
PR-URL: libuv#1246 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
1 parent 2ce5734 commit d59d6e6

File tree

34 files changed

+1785
-0
lines changed

34 files changed

+1785
-0
lines changed

docs/code/cgi/main.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include <inttypes.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <uv.h>
6+
7+
uv_loop_t *loop;
8+
uv_process_t child_req;
9+
uv_process_options_t options;
10+
11+
void cleanup_handles(uv_process_t *req, int64_t exit_status, int term_signal) {
12+
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
13+
uv_close((uv_handle_t*) req->data, NULL);
14+
uv_close((uv_handle_t*) req, NULL);
15+
}
16+
17+
void invoke_cgi_script(uv_tcp_t *client) {
18+
size_t size = 500;
19+
char path[size];
20+
uv_exepath(path, &size);
21+
strcpy(path + (strlen(path) - strlen("cgi")), "tick");
22+
23+
char* args[2];
24+
args[0] = path;
25+
args[1] = NULL;
26+
27+
/* ... finding the executable path and setting up arguments ... */
28+
29+
options.stdio_count = 3;
30+
uv_stdio_container_t child_stdio[3];
31+
child_stdio[0].flags = UV_IGNORE;
32+
child_stdio[1].flags = UV_INHERIT_STREAM;
33+
child_stdio[1].data.stream = (uv_stream_t*) client;
34+
child_stdio[2].flags = UV_IGNORE;
35+
options.stdio = child_stdio;
36+
37+
options.exit_cb = cleanup_handles;
38+
options.file = args[0];
39+
options.args = args;
40+
41+
// Set this so we can close the socket after the child process exits.
42+
child_req.data = (void*) client;
43+
int r;
44+
if ((r = uv_spawn(loop, &child_req, &options))) {
45+
fprintf(stderr, "%s\n", uv_strerror(r));
46+
return;
47+
}
48+
}
49+
50+
void on_new_connection(uv_stream_t *server, int status) {
51+
if (status == -1) {
52+
// error!
53+
return;
54+
}
55+
56+
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
57+
uv_tcp_init(loop, client);
58+
if (uv_accept(server, (uv_stream_t*) client) == 0) {
59+
invoke_cgi_script(client);
60+
}
61+
else {
62+
uv_close((uv_handle_t*) client, NULL);
63+
}
64+
}
65+
66+
int main() {
67+
loop = uv_default_loop();
68+
69+
uv_tcp_t server;
70+
uv_tcp_init(loop, &server);
71+
72+
struct sockaddr_in bind_addr;
73+
uv_ip4_addr("0.0.0.0", 7000, &bind_addr);
74+
uv_tcp_bind(&server, (const struct sockaddr *)&bind_addr, 0);
75+
int r = uv_listen((uv_stream_t*) &server, 128, on_new_connection);
76+
if (r) {
77+
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
78+
return 1;
79+
}
80+
return uv_run(loop, UV_RUN_DEFAULT);
81+
}

docs/code/cgi/tick.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <stdio.h>
2+
#include <unistd.h>
3+
4+
int main() {
5+
int i;
6+
for (i = 0; i < 10; i++) {
7+
printf("tick\n");
8+
fflush(stdout);
9+
sleep(1);
10+
}
11+
printf("BOOM!\n");
12+
return 0;
13+
}

docs/code/detach/main.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <stdio.h>
2+
3+
#include <uv.h>
4+
5+
uv_loop_t *loop;
6+
uv_process_t child_req;
7+
uv_process_options_t options;
8+
9+
int main() {
10+
loop = uv_default_loop();
11+
12+
char* args[3];
13+
args[0] = "sleep";
14+
args[1] = "100";
15+
args[2] = NULL;
16+
17+
options.exit_cb = NULL;
18+
options.file = "sleep";
19+
options.args = args;
20+
options.flags = UV_PROCESS_DETACHED;
21+
22+
int r;
23+
if ((r = uv_spawn(loop, &child_req, &options))) {
24+
fprintf(stderr, "%s\n", uv_strerror(r));
25+
return 1;
26+
}
27+
fprintf(stderr, "Launched sleep with PID %d\n", child_req.pid);
28+
uv_unref((uv_handle_t*) &child_req);
29+
30+
return uv_run(loop, UV_RUN_DEFAULT);
31+
}

docs/code/dns/main.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <uv.h>
5+
6+
uv_loop_t *loop;
7+
8+
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
9+
buf->base = malloc(suggested_size);
10+
buf->len = suggested_size;
11+
}
12+
13+
void on_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
14+
if (nread < 0) {
15+
if (nread != UV_EOF)
16+
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
17+
uv_close((uv_handle_t*) client, NULL);
18+
free(buf->base);
19+
free(client);
20+
return;
21+
}
22+
23+
char *data = (char*) malloc(sizeof(char) * (nread+1));
24+
data[nread] = '\0';
25+
strncpy(data, buf->base, nread);
26+
27+
fprintf(stderr, "%s", data);
28+
free(data);
29+
free(buf->base);
30+
}
31+
32+
void on_connect(uv_connect_t *req, int status) {
33+
if (status < 0) {
34+
fprintf(stderr, "connect failed error %s\n", uv_err_name(status));
35+
free(req);
36+
return;
37+
}
38+
39+
uv_read_start((uv_stream_t*) req->handle, alloc_buffer, on_read);
40+
free(req);
41+
}
42+
43+
void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) {
44+
if (status < 0) {
45+
fprintf(stderr, "getaddrinfo callback error %s\n", uv_err_name(status));
46+
return;
47+
}
48+
49+
char addr[17] = {'\0'};
50+
uv_ip4_name((struct sockaddr_in*) res->ai_addr, addr, 16);
51+
fprintf(stderr, "%s\n", addr);
52+
53+
uv_connect_t *connect_req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
54+
uv_tcp_t *socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
55+
uv_tcp_init(loop, socket);
56+
57+
uv_tcp_connect(connect_req, socket, (const struct sockaddr*) res->ai_addr, on_connect);
58+
59+
uv_freeaddrinfo(res);
60+
}
61+
62+
int main() {
63+
loop = uv_default_loop();
64+
65+
struct addrinfo hints;
66+
hints.ai_family = PF_INET;
67+
hints.ai_socktype = SOCK_STREAM;
68+
hints.ai_protocol = IPPROTO_TCP;
69+
hints.ai_flags = 0;
70+
71+
uv_getaddrinfo_t resolver;
72+
fprintf(stderr, "irc.freenode.net is... ");
73+
int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.freenode.net", "6667", &hints);
74+
75+
if (r) {
76+
fprintf(stderr, "getaddrinfo call error %s\n", uv_err_name(r));
77+
return 1;
78+
}
79+
return uv_run(loop, UV_RUN_DEFAULT);
80+
}

docs/code/helloworld/main.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <uv.h>
4+
5+
int main() {
6+
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
7+
uv_loop_init(loop);
8+
9+
printf("Now quitting.\n");
10+
uv_run(loop, UV_RUN_DEFAULT);
11+
12+
uv_loop_close(loop);
13+
free(loop);
14+
return 0;
15+
}

docs/code/idle-basic/main.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <stdio.h>
2+
#include <uv.h>
3+
4+
int64_t counter = 0;
5+
6+
void wait_for_a_while(uv_idle_t* handle) {
7+
counter++;
8+
9+
if (counter >= 10e6)
10+
uv_idle_stop(handle);
11+
}
12+
13+
int main() {
14+
uv_idle_t idler;
15+
16+
uv_idle_init(uv_default_loop(), &idler);
17+
uv_idle_start(&idler, wait_for_a_while);
18+
19+
printf("Idling...\n");
20+
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
21+
22+
uv_loop_close(uv_default_loop());
23+
return 0;
24+
}

docs/code/idle-compute/main.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include <stdio.h>
2+
3+
#include <uv.h>
4+
5+
uv_loop_t *loop;
6+
uv_fs_t stdin_watcher;
7+
uv_idle_t idler;
8+
char buffer[1024];
9+
10+
void crunch_away(uv_idle_t* handle) {
11+
// Compute extra-terrestrial life
12+
// fold proteins
13+
// computer another digit of PI
14+
// or similar
15+
fprintf(stderr, "Computing PI...\n");
16+
// just to avoid overwhelming your terminal emulator
17+
uv_idle_stop(handle);
18+
}
19+
20+
void on_type(uv_fs_t *req) {
21+
if (stdin_watcher.result > 0) {
22+
buffer[stdin_watcher.result] = '\0';
23+
printf("Typed %s\n", buffer);
24+
25+
uv_buf_t buf = uv_buf_init(buffer, 1024);
26+
uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type);
27+
uv_idle_start(&idler, crunch_away);
28+
}
29+
else if (stdin_watcher.result < 0) {
30+
fprintf(stderr, "error opening file: %s\n", uv_strerror(req->result));
31+
}
32+
}
33+
34+
int main() {
35+
loop = uv_default_loop();
36+
37+
uv_idle_init(loop, &idler);
38+
39+
uv_buf_t buf = uv_buf_init(buffer, 1024);
40+
uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type);
41+
uv_idle_start(&idler, crunch_away);
42+
return uv_run(loop, UV_RUN_DEFAULT);
43+
}

docs/code/interfaces/main.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <stdio.h>
2+
#include <uv.h>
3+
4+
int main() {
5+
char buf[512];
6+
uv_interface_address_t *info;
7+
int count, i;
8+
9+
uv_interface_addresses(&info, &count);
10+
i = count;
11+
12+
printf("Number of interfaces: %d\n", count);
13+
while (i--) {
14+
uv_interface_address_t interface = info[i];
15+
16+
printf("Name: %s\n", interface.name);
17+
printf("Internal? %s\n", interface.is_internal ? "Yes" : "No");
18+
19+
if (interface.address.address4.sin_family == AF_INET) {
20+
uv_ip4_name(&interface.address.address4, buf, sizeof(buf));
21+
printf("IPv4 address: %s\n", buf);
22+
}
23+
else if (interface.address.address4.sin_family == AF_INET6) {
24+
uv_ip6_name(&interface.address.address6, buf, sizeof(buf));
25+
printf("IPv6 address: %s\n", buf);
26+
}
27+
28+
printf("\n");
29+
}
30+
31+
uv_free_interface_addresses(info, count);
32+
return 0;
33+
}

docs/code/locks/main.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <stdio.h>
2+
#include <uv.h>
3+
4+
uv_barrier_t blocker;
5+
uv_rwlock_t numlock;
6+
int shared_num;
7+
8+
void reader(void *n)
9+
{
10+
int num = *(int *)n;
11+
int i;
12+
for (i = 0; i < 20; i++) {
13+
uv_rwlock_rdlock(&numlock);
14+
printf("Reader %d: acquired lock\n", num);
15+
printf("Reader %d: shared num = %d\n", num, shared_num);
16+
uv_rwlock_rdunlock(&numlock);
17+
printf("Reader %d: released lock\n", num);
18+
}
19+
uv_barrier_wait(&blocker);
20+
}
21+
22+
void writer(void *n)
23+
{
24+
int num = *(int *)n;
25+
int i;
26+
for (i = 0; i < 20; i++) {
27+
uv_rwlock_wrlock(&numlock);
28+
printf("Writer %d: acquired lock\n", num);
29+
shared_num++;
30+
printf("Writer %d: incremented shared num = %d\n", num, shared_num);
31+
uv_rwlock_wrunlock(&numlock);
32+
printf("Writer %d: released lock\n", num);
33+
}
34+
uv_barrier_wait(&blocker);
35+
}
36+
37+
int main()
38+
{
39+
uv_barrier_init(&blocker, 4);
40+
41+
shared_num = 0;
42+
uv_rwlock_init(&numlock);
43+
44+
uv_thread_t threads[3];
45+
46+
int thread_nums[] = {1, 2, 1};
47+
uv_thread_create(&threads[0], reader, &thread_nums[0]);
48+
uv_thread_create(&threads[1], reader, &thread_nums[1]);
49+
50+
uv_thread_create(&threads[2], writer, &thread_nums[2]);
51+
52+
uv_barrier_wait(&blocker);
53+
uv_barrier_destroy(&blocker);
54+
55+
uv_rwlock_destroy(&numlock);
56+
return 0;
57+
}

0 commit comments

Comments
 (0)