asyncengine 0.0.1.testing1 → 0.0.2.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +3 -0
- data/Rakefile +38 -0
- data/asyncengine.gemspec +8 -4
- data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
- data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
- data/ext/asyncengine/ae_handle_common.c +193 -48
- data/ext/asyncengine/ae_handle_common.h +40 -13
- data/ext/asyncengine/ae_ip_utils.c +246 -0
- data/ext/asyncengine/ae_ip_utils.h +25 -0
- data/ext/asyncengine/ae_next_tick.c +81 -21
- data/ext/asyncengine/ae_next_tick.h +4 -2
- data/ext/asyncengine/ae_resolver.c +156 -0
- data/ext/asyncengine/ae_resolver.h +10 -0
- data/ext/asyncengine/ae_tcp.c +908 -0
- data/ext/asyncengine/ae_tcp.h +20 -0
- data/ext/asyncengine/ae_timer.c +355 -81
- data/ext/asyncengine/ae_timer.h +11 -4
- data/ext/asyncengine/ae_udp.c +579 -13
- data/ext/asyncengine/ae_udp.h +15 -2
- data/ext/asyncengine/ae_utils.c +192 -0
- data/ext/asyncengine/ae_utils.h +16 -0
- data/ext/asyncengine/asyncengine_ruby.c +469 -26
- data/ext/asyncengine/asyncengine_ruby.h +49 -11
- data/ext/asyncengine/debug.h +68 -0
- data/ext/asyncengine/extconf.rb +26 -2
- data/ext/asyncengine/ip_parser.c +5954 -0
- data/ext/asyncengine/ip_parser.h +16 -0
- data/ext/asyncengine/libuv/AUTHORS +16 -0
- data/ext/asyncengine/libuv/common.gypi +4 -4
- data/ext/asyncengine/libuv/config-mingw.mk +6 -6
- data/ext/asyncengine/libuv/config-unix.mk +13 -13
- data/ext/asyncengine/libuv/gyp_uv +5 -1
- data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
- data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
- data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
- data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
- data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
- data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
- data/ext/asyncengine/libuv/include/uv.h +353 -88
- data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
- data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
- data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
- data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
- data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
- data/ext/asyncengine/libuv/src/cares.c +225 -0
- data/ext/asyncengine/libuv/src/cares.o +0 -0
- data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
- data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
- data/ext/asyncengine/libuv/src/unix/async.c +78 -17
- data/ext/asyncengine/libuv/src/unix/async.o +0 -0
- data/ext/asyncengine/libuv/src/unix/core.c +305 -213
- data/ext/asyncengine/libuv/src/unix/core.o +0 -0
- data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
- data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
- data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
- data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
- data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
- data/ext/asyncengine/libuv/src/unix/error.c +6 -0
- data/ext/asyncengine/libuv/src/unix/error.o +0 -0
- data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
- data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
- data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
- data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
- data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
- data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
- data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
- data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
- data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
- data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
- data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
- data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
- data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
- data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
- data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
- data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
- data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
- data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
- data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
- data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
- data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
- data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
- data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
- data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
- data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
- data/ext/asyncengine/libuv/src/unix/process.c +193 -115
- data/ext/asyncengine/libuv/src/unix/process.o +0 -0
- data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
- data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
- data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
- data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
- data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
- data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
- data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
- data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
- data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
- data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
- data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
- data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
- data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
- data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
- data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
- data/ext/asyncengine/libuv/src/uv-common.c +68 -38
- data/ext/asyncengine/libuv/src/uv-common.h +104 -20
- data/ext/asyncengine/libuv/src/uv-common.o +0 -0
- data/ext/asyncengine/libuv/src/win/async.c +20 -17
- data/ext/asyncengine/libuv/src/win/core.c +44 -31
- data/ext/asyncengine/libuv/src/win/dl.c +40 -36
- data/ext/asyncengine/libuv/src/win/error.c +21 -1
- data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
- data/ext/asyncengine/libuv/src/win/fs.c +541 -189
- data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
- data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
- data/ext/asyncengine/libuv/src/win/handle.c +26 -101
- data/ext/asyncengine/libuv/src/win/internal.h +92 -107
- data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
- data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
- data/ext/asyncengine/libuv/src/win/poll.c +618 -0
- data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
- data/ext/asyncengine/libuv/src/win/process.c +147 -274
- data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
- data/ext/asyncengine/libuv/src/win/req.c +0 -149
- data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
- data/ext/asyncengine/libuv/src/win/stream.c +9 -43
- data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
- data/ext/asyncengine/libuv/src/win/thread.c +42 -2
- data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
- data/ext/asyncengine/libuv/src/win/timer.c +13 -63
- data/ext/asyncengine/libuv/src/win/tty.c +26 -20
- data/ext/asyncengine/libuv/src/win/udp.c +26 -17
- data/ext/asyncengine/libuv/src/win/util.c +312 -167
- data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
- data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
- data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
- data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
- data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
- data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
- data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
- data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
- data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
- data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
- data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
- data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
- data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
- data/ext/asyncengine/libuv/test/echo-server.c +8 -0
- data/ext/asyncengine/libuv/test/run-tests.c +30 -0
- data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
- data/ext/asyncengine/libuv/test/runner-win.c +5 -63
- data/ext/asyncengine/libuv/test/runner.c +10 -1
- data/ext/asyncengine/libuv/test/task.h +0 -8
- data/ext/asyncengine/libuv/test/test-async.c +43 -141
- data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
- data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
- data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
- data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
- data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
- data/ext/asyncengine/libuv/test/test-fs.c +114 -2
- data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
- data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
- data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
- data/ext/asyncengine/libuv/test/test-list.h +59 -9
- data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
- data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
- data/ext/asyncengine/libuv/test/test-poll.c +573 -0
- data/ext/asyncengine/libuv/test/test-ref.c +79 -63
- data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
- data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
- data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
- data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
- data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
- data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
- data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
- data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
- data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
- data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
- data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
- data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
- data/ext/asyncengine/libuv/test/test-timer.c +23 -1
- data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
- data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
- data/ext/asyncengine/libuv/uv.gyp +26 -9
- data/ext/asyncengine/rb_utilities.c +54 -0
- data/ext/asyncengine/rb_utilities.h +63 -0
- data/lib/asyncengine.rb +45 -38
- data/lib/asyncengine/asyncengine_ext.so +0 -0
- data/lib/asyncengine/debug.rb +37 -0
- data/lib/asyncengine/handle.rb +9 -0
- data/lib/asyncengine/tcp.rb +28 -0
- data/lib/asyncengine/timer.rb +18 -28
- data/lib/asyncengine/udp.rb +29 -0
- data/lib/asyncengine/utils.rb +32 -0
- data/lib/asyncengine/uv_error.rb +17 -0
- data/lib/asyncengine/version.rb +9 -1
- data/test/ae_test_helper.rb +62 -0
- data/test/test_basic.rb +169 -0
- data/test/test_call_from_other_thread.rb +55 -0
- data/test/test_error.rb +92 -0
- data/test/test_ip_utils.rb +44 -0
- data/test/test_next_tick.rb +37 -0
- data/test/test_resolver.rb +51 -0
- data/test/test_threads.rb +69 -0
- data/test/test_timer.rb +95 -0
- data/test/test_udp.rb +216 -0
- data/test/test_utils.rb +49 -0
- metadata +84 -57
- data/ext/asyncengine/libuv/mkmf.log +0 -24
- data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
- data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
- data/ext/asyncengine/libuv/src/unix/check.o +0 -0
- data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
- data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
- data/ext/asyncengine/libuv/src/win/cares.c +0 -290
- data/lib/asyncengine/errors.rb +0 -5
- data/lib/asyncengine/next_tick.rb +0 -24
data/ext/asyncengine/ae_udp.h
CHANGED
|
@@ -2,9 +2,22 @@
|
|
|
2
2
|
#define AE_UDP_H
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
void init_ae_udp();
|
|
5
|
+
void init_ae_udp(void);
|
|
6
6
|
|
|
7
|
-
VALUE
|
|
7
|
+
static VALUE AsyncEngineUdpSocket_new(int argc, VALUE *argv, VALUE self);
|
|
8
|
+
static VALUE AsyncEngineUdpSocket_send_datagram(int argc, VALUE *argv, VALUE self);
|
|
9
|
+
static VALUE AsyncEngineUdpSocket_local_address(VALUE self);
|
|
10
|
+
static VALUE AsyncEngineUdpSocket_ip_type(VALUE self);
|
|
11
|
+
static VALUE AsyncEngineUdpSocket_pause(VALUE self);
|
|
12
|
+
static VALUE AsyncEngineUdpSocket_resume(VALUE self);
|
|
13
|
+
static VALUE AsyncEngineUdpSocket_is_paused(VALUE self);
|
|
14
|
+
static VALUE AsyncEngineUdpSocket_set_encoding_external(VALUE self);
|
|
15
|
+
static VALUE AsyncEngineUdpSocket_set_encoding_utf8(VALUE self);
|
|
16
|
+
static VALUE AsyncEngineUdpSocket_set_encoding_ascii(VALUE self);
|
|
17
|
+
static VALUE AsyncEngineUdpSocket_encoding(VALUE self);
|
|
18
|
+
static VALUE AsyncEngineUdpSocket_is_alive(VALUE self);
|
|
19
|
+
static VALUE AsyncEngineUdpSocket_close(VALUE self);
|
|
20
|
+
static VALUE AsyncEngineUdpSocket_destroy(VALUE self);
|
|
8
21
|
|
|
9
22
|
|
|
10
23
|
#endif /* AE_UDP_H */
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#include "asyncengine_ruby.h"
|
|
2
|
+
#include "ae_ip_utils.h"
|
|
3
|
+
#include "ae_utils.h"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
VALUE mAsyncEngineUtils;
|
|
7
|
+
VALUE cAsyncEngineUtilsNetworkInterface;
|
|
8
|
+
VALUE cAsyncEngineUtilsCpuInfo;
|
|
9
|
+
|
|
10
|
+
// Atributes for AE::Utils::NetworkInterface.
|
|
11
|
+
static ID att_name;
|
|
12
|
+
static ID att_is_internal;
|
|
13
|
+
static ID att_ip_type;
|
|
14
|
+
static ID att_ip;
|
|
15
|
+
|
|
16
|
+
// Atributes for AE::Utils::CpuInfo.
|
|
17
|
+
static ID att_model;
|
|
18
|
+
static ID att_speed;
|
|
19
|
+
static ID att_time_sys;
|
|
20
|
+
static ID att_time_user;
|
|
21
|
+
static ID att_time_idle;
|
|
22
|
+
static ID att_time_irq;
|
|
23
|
+
static ID att_time_nice;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
void init_ae_utils(void)
|
|
27
|
+
{
|
|
28
|
+
mAsyncEngineUtils = rb_define_module_under(mAsyncEngine, "Utils");
|
|
29
|
+
cAsyncEngineUtilsNetworkInterface = rb_define_class_under(mAsyncEngineUtils, "NetworkInterface", rb_cObject);
|
|
30
|
+
cAsyncEngineUtilsCpuInfo = rb_define_class_under(mAsyncEngineUtils, "CpuInfo", rb_cObject);
|
|
31
|
+
|
|
32
|
+
rb_define_module_function(mAsyncEngineUtils, "get_hrtime", AsyncEngineUtils_get_hrtime, 0);
|
|
33
|
+
rb_define_module_function(mAsyncEngineUtils, "get_total_memory", AsyncEngineUtils_get_total_memory, 0);
|
|
34
|
+
rb_define_module_function(mAsyncEngineUtils, "get_free_memory", AsyncEngineUtils_get_free_memory, 0);
|
|
35
|
+
rb_define_module_function(mAsyncEngineUtils, "get_loadavg", AsyncEngineUtils_get_loadavg, 0);
|
|
36
|
+
rb_define_module_function(mAsyncEngineUtils, "get_uptime", AsyncEngineUtils_get_uptime, 0);
|
|
37
|
+
rb_define_module_function(mAsyncEngineUtils, "get_network_interfaces", AsyncEngineUtils_get_network_interfaces, 0);
|
|
38
|
+
rb_define_module_function(mAsyncEngineUtils, "get_cpu_info", AsyncEngineUtils_get_cpu_info, 0);
|
|
39
|
+
|
|
40
|
+
att_name = rb_intern("@name");
|
|
41
|
+
att_is_internal = rb_intern("@is_internal");
|
|
42
|
+
att_ip_type = rb_intern("@ip_type");
|
|
43
|
+
att_ip = rb_intern("@ip");
|
|
44
|
+
att_model = rb_intern("@model");
|
|
45
|
+
att_speed = rb_intern("@speed");
|
|
46
|
+
att_time_sys = rb_intern("@time_sys");
|
|
47
|
+
att_time_user = rb_intern("@time_user");
|
|
48
|
+
att_time_idle = rb_intern("@time_idle");
|
|
49
|
+
att_time_irq = rb_intern("@time_irq");
|
|
50
|
+
att_time_nice = rb_intern("@time_nice");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
* Returns the current high-resolution real time. This is expressed in
|
|
56
|
+
* nanoseconds. It is relative to an arbitrary time in the past. It is not
|
|
57
|
+
* related to the time of day and therefore not subject to clock drift. The
|
|
58
|
+
* primary use is for measuring performance between intervals.
|
|
59
|
+
*/
|
|
60
|
+
VALUE AsyncEngineUtils_get_hrtime(VALUE self)
|
|
61
|
+
{
|
|
62
|
+
AE_TRACE();
|
|
63
|
+
|
|
64
|
+
return LONG2FIX((long)uv_hrtime());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
/* Gets total memory in bytes */
|
|
69
|
+
VALUE AsyncEngineUtils_get_total_memory(VALUE self)
|
|
70
|
+
{
|
|
71
|
+
AE_TRACE();
|
|
72
|
+
|
|
73
|
+
return LONG2FIX((long)uv_get_total_memory());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
/* Gets free memory in bytes */
|
|
78
|
+
VALUE AsyncEngineUtils_get_free_memory(VALUE self)
|
|
79
|
+
{
|
|
80
|
+
AE_TRACE();
|
|
81
|
+
|
|
82
|
+
return LONG2FIX((long)uv_get_free_memory());
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
/* Returns an Array with loadavg data (Float values). */
|
|
87
|
+
VALUE AsyncEngineUtils_get_loadavg(VALUE self)
|
|
88
|
+
{
|
|
89
|
+
AE_TRACE();
|
|
90
|
+
|
|
91
|
+
double avg[3];
|
|
92
|
+
uv_loadavg(avg);
|
|
93
|
+
|
|
94
|
+
return rb_ary_new3(3, rb_float_new(avg[0]), rb_float_new(avg[1]), rb_float_new(avg[2]));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
/* Returns system uptime value in seconds .*/
|
|
99
|
+
VALUE AsyncEngineUtils_get_uptime(VALUE self)
|
|
100
|
+
{
|
|
101
|
+
AE_TRACE();
|
|
102
|
+
|
|
103
|
+
double uptime;
|
|
104
|
+
uv_err_t error;
|
|
105
|
+
|
|
106
|
+
error = uv_uptime(&uptime);
|
|
107
|
+
if (error.code)
|
|
108
|
+
ae_raise_uv_error(error.code);
|
|
109
|
+
|
|
110
|
+
return rb_float_new(uptime);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
VALUE AsyncEngineUtils_get_network_interfaces(VALUE self)
|
|
115
|
+
{
|
|
116
|
+
AE_TRACE();
|
|
117
|
+
|
|
118
|
+
int i, num_interfaces;
|
|
119
|
+
char ip[INET6_ADDRSTRLEN+1];
|
|
120
|
+
uv_interface_address_t* interfaces;
|
|
121
|
+
uv_err_t error;
|
|
122
|
+
VALUE ae_network_interface, result_array;
|
|
123
|
+
|
|
124
|
+
error = uv_interface_addresses(&interfaces, &num_interfaces);
|
|
125
|
+
if (error.code)
|
|
126
|
+
ae_raise_uv_error(error.code);
|
|
127
|
+
|
|
128
|
+
result_array = rb_ary_new2(num_interfaces);
|
|
129
|
+
|
|
130
|
+
for (i = 0; i < num_interfaces; i++) {
|
|
131
|
+
ae_network_interface = rb_obj_alloc(cAsyncEngineUtilsNetworkInterface);
|
|
132
|
+
rb_ivar_set(ae_network_interface, att_name, rb_str_new2(interfaces[i].name));
|
|
133
|
+
rb_ivar_set(ae_network_interface, att_is_internal, (interfaces[i].is_internal ? Qtrue : Qfalse));
|
|
134
|
+
|
|
135
|
+
if (interfaces[i].address.address4.sin_family == AF_INET) {
|
|
136
|
+
rb_ivar_set(ae_network_interface, att_ip_type, symbol_ipv4);
|
|
137
|
+
uv_ip4_name(&interfaces[i].address.address4, ip, INET_ADDRSTRLEN);
|
|
138
|
+
rb_ivar_set(ae_network_interface, att_ip, rb_str_new2(ip));
|
|
139
|
+
}
|
|
140
|
+
else if (interfaces[i].address.address4.sin_family == AF_INET6) {
|
|
141
|
+
rb_ivar_set(ae_network_interface, att_ip_type, symbol_ipv6);
|
|
142
|
+
uv_ip6_name(&interfaces[i].address.address6, ip, INET6_ADDRSTRLEN);
|
|
143
|
+
rb_ivar_set(ae_network_interface, att_ip, rb_str_new2(ip));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
rb_ary_store(result_array, i, ae_network_interface);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
uv_free_interface_addresses(interfaces, num_interfaces);
|
|
150
|
+
|
|
151
|
+
return result_array;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
VALUE AsyncEngineUtils_get_cpu_info(VALUE self)
|
|
156
|
+
{
|
|
157
|
+
AE_TRACE();
|
|
158
|
+
|
|
159
|
+
int i, num_cpus;
|
|
160
|
+
uv_cpu_info_t* cpus;
|
|
161
|
+
uv_err_t error;
|
|
162
|
+
uint64_t cpu_times_total;
|
|
163
|
+
VALUE ae_cpu_info, result_array;
|
|
164
|
+
|
|
165
|
+
error = uv_cpu_info(&cpus, &num_cpus);
|
|
166
|
+
if (error.code)
|
|
167
|
+
ae_raise_uv_error(error.code);
|
|
168
|
+
|
|
169
|
+
result_array = rb_ary_new2(num_cpus);
|
|
170
|
+
|
|
171
|
+
for (i = 0; i < num_cpus; i++) {
|
|
172
|
+
ae_cpu_info = rb_obj_alloc(cAsyncEngineUtilsCpuInfo);
|
|
173
|
+
|
|
174
|
+
rb_ivar_set(ae_cpu_info, att_model, rb_str_new2(cpus[i].model));
|
|
175
|
+
rb_ivar_set(ae_cpu_info, att_speed, INT2FIX(cpus[i].speed));
|
|
176
|
+
|
|
177
|
+
cpu_times_total = cpus[i].cpu_times.sys + cpus[i].cpu_times.user + cpus[i].cpu_times.idle +
|
|
178
|
+
cpus[i].cpu_times.irq + cpus[i].cpu_times.nice;
|
|
179
|
+
|
|
180
|
+
rb_ivar_set(ae_cpu_info, att_time_sys, rb_float_new((cpus[i].cpu_times.sys * 100.0 / cpu_times_total)));
|
|
181
|
+
rb_ivar_set(ae_cpu_info, att_time_user, rb_float_new((cpus[i].cpu_times.user * 100.0 / cpu_times_total)));
|
|
182
|
+
rb_ivar_set(ae_cpu_info, att_time_idle, rb_float_new((cpus[i].cpu_times.idle * 100.0 / cpu_times_total)));
|
|
183
|
+
rb_ivar_set(ae_cpu_info, att_time_irq, rb_float_new((cpus[i].cpu_times.irq * 100.0 / cpu_times_total)));
|
|
184
|
+
rb_ivar_set(ae_cpu_info, att_time_nice, rb_float_new((cpus[i].cpu_times.nice * 100.0 / cpu_times_total)));
|
|
185
|
+
|
|
186
|
+
rb_ary_push(result_array, ae_cpu_info);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
uv_free_cpu_info(cpus, num_cpus);
|
|
190
|
+
|
|
191
|
+
return result_array;
|
|
192
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#ifndef AE_UTILS_H
|
|
2
|
+
#define AE_UTILS_H
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
void init_ae_utils(void);
|
|
6
|
+
|
|
7
|
+
VALUE AsyncEngineUtils_get_hrtime(VALUE self);
|
|
8
|
+
VALUE AsyncEngineUtils_get_total_memory(VALUE self);
|
|
9
|
+
VALUE AsyncEngineUtils_get_free_memory(VALUE self);
|
|
10
|
+
VALUE AsyncEngineUtils_get_loadavg(VALUE self);
|
|
11
|
+
VALUE AsyncEngineUtils_get_uptime(VALUE self);
|
|
12
|
+
VALUE AsyncEngineUtils_get_network_interfaces(VALUE self);
|
|
13
|
+
VALUE AsyncEngineUtils_get_cpu_info(VALUE self);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
#endif /* AE_UTILS_H */
|
|
@@ -1,56 +1,452 @@
|
|
|
1
1
|
#include "asyncengine_ruby.h"
|
|
2
2
|
#include "ae_handle_common.h"
|
|
3
|
-
#include "
|
|
3
|
+
#include "ae_utils.h"
|
|
4
|
+
#include "ae_ip_utils.h"
|
|
5
|
+
#include "ae_call_from_other_thread.h"
|
|
4
6
|
#include "ae_next_tick.h"
|
|
7
|
+
#include "ae_timer.h"
|
|
5
8
|
#include "ae_udp.h"
|
|
9
|
+
#include "ae_tcp.h"
|
|
10
|
+
#include "ae_resolver.h"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
static VALUE mProcess;
|
|
14
|
+
static VALUE mKernel;
|
|
15
|
+
|
|
16
|
+
static VALUE AE_thread;
|
|
17
|
+
static VALUE AE_pid;
|
|
18
|
+
static VALUE AE_barrier;
|
|
19
|
+
|
|
20
|
+
static ID att_handles;
|
|
21
|
+
static ID att_procs;
|
|
22
|
+
static ID att_next_tick_procs;
|
|
23
|
+
static ID att_call_from_other_thread_procs;
|
|
24
|
+
static ID att_user_error_handler;
|
|
25
|
+
static ID att_exit_error;
|
|
26
|
+
static ID att_on_exit_procs;
|
|
27
|
+
|
|
28
|
+
static ID method_destroy;
|
|
29
|
+
static ID method_clear;
|
|
30
|
+
static ID method_next_tick;
|
|
31
|
+
static ID method_call_from_other_thread;
|
|
32
|
+
static ID method_pid;
|
|
33
|
+
static ID method_raise;
|
|
34
|
+
static ID method_call;
|
|
35
|
+
|
|
36
|
+
static uv_async_t* ae_ubf_uv_async;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/** Pre-declaration of static functions. */
|
|
40
|
+
|
|
41
|
+
static VALUE uv_run_without_gvl(void);
|
|
42
|
+
static void ae_ubf(void);
|
|
43
|
+
static void ae_ubf_uv_async_callback(uv_async_t* handle, int status);
|
|
44
|
+
static void ae_release_loop(void);
|
|
45
|
+
static int destroy_handle(VALUE key, VALUE handle, VALUE in);
|
|
46
|
+
static VALUE destroy_handle_with_rb_protect(VALUE handle);
|
|
47
|
+
static int ae_is_running_thread(void);
|
|
48
|
+
static VALUE ae_handle_error_with_rb_protect(VALUE error);
|
|
49
|
+
|
|
6
50
|
|
|
51
|
+
/** TODO: Temporal functions for debugging: libuv active handlers and requests counters. */
|
|
7
52
|
|
|
8
53
|
static
|
|
9
|
-
|
|
54
|
+
int ae_uv_num_active_handlers(void)
|
|
10
55
|
{
|
|
11
56
|
AE_TRACE();
|
|
12
57
|
|
|
13
|
-
|
|
14
|
-
|
|
58
|
+
if (AE_status == AE_STOPPED)
|
|
59
|
+
return 0;
|
|
15
60
|
|
|
16
|
-
|
|
17
|
-
if (uv_loop_refcount(uv_default_loop()) == 1)
|
|
18
|
-
uv_close((uv_handle_t *)handle, ae_handle_close_callback_0);
|
|
61
|
+
return AE_uv_loop->active_handles;
|
|
19
62
|
}
|
|
20
63
|
|
|
21
64
|
|
|
22
65
|
static
|
|
23
|
-
VALUE
|
|
66
|
+
VALUE AsyncEngine_num_uv_active_handles(VALUE self)
|
|
24
67
|
{
|
|
25
68
|
AE_TRACE();
|
|
26
69
|
|
|
27
|
-
|
|
70
|
+
return INT2FIX(ae_uv_num_active_handlers());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
static
|
|
75
|
+
int ae_uv_num_active_reqs(void)
|
|
76
|
+
{
|
|
77
|
+
AE_TRACE();
|
|
78
|
+
|
|
79
|
+
if (AE_status == AE_STOPPED)
|
|
80
|
+
return 0;
|
|
81
|
+
|
|
82
|
+
ngx_queue_t *q;
|
|
83
|
+
int count = 0;
|
|
84
|
+
ngx_queue_foreach(q, &AE_uv_loop->active_reqs)
|
|
85
|
+
count++;
|
|
86
|
+
return count;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
static
|
|
91
|
+
VALUE AsyncEngine_num_uv_active_reqs(VALUE self)
|
|
92
|
+
{
|
|
93
|
+
AE_TRACE();
|
|
94
|
+
|
|
95
|
+
return INT2FIX(ae_uv_num_active_reqs());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
/** AE.run method. */
|
|
100
|
+
|
|
101
|
+
static
|
|
102
|
+
VALUE AsyncEngine_run(int argc, VALUE *argv, VALUE self)
|
|
103
|
+
{
|
|
104
|
+
AE_TRACE();
|
|
105
|
+
VALUE proc, captured_error, on_exit_procs;
|
|
106
|
+
int r, i;
|
|
107
|
+
|
|
108
|
+
AE_RB_CHECK_NUM_ARGS(0,1);
|
|
109
|
+
AE_RB_ENSURE_BLOCK_OR_PROC(1, proc);
|
|
110
|
+
|
|
111
|
+
if (AE_status == AE_RUNNING && (rb_funcall2(mProcess, method_pid, 0, NULL) != AE_pid))
|
|
112
|
+
rb_raise(eAsyncEngineError, "cannot run AsyncEngine from a forked process while already running");
|
|
113
|
+
|
|
114
|
+
// If already running pass the Proc to the reactor and return true.
|
|
115
|
+
if (AE_status == AE_RUNNING) {
|
|
116
|
+
if (ae_is_running_thread())
|
|
117
|
+
rb_funcall2(mAsyncEngine, method_next_tick, 1, &proc);
|
|
118
|
+
else
|
|
119
|
+
rb_funcall2(mAsyncEngine, method_call_from_other_thread, 1, &proc);
|
|
28
120
|
return Qtrue;
|
|
29
121
|
}
|
|
30
|
-
|
|
31
|
-
|
|
122
|
+
|
|
123
|
+
// Acquire the barrier lock.
|
|
124
|
+
rb_barrier_wait(AE_barrier);
|
|
125
|
+
|
|
126
|
+
/* Set the UV loop. */
|
|
127
|
+
AE_uv_loop = uv_default_loop();
|
|
128
|
+
|
|
129
|
+
// Mark current thread and PID.
|
|
130
|
+
AE_thread = rb_thread_current();
|
|
131
|
+
AE_pid = rb_funcall2(mProcess, method_pid, 0, NULL);
|
|
132
|
+
|
|
133
|
+
// Get the VALUEs for @_handles and @_procs (faster).
|
|
134
|
+
AE_handles = rb_ivar_get(mAsyncEngine, att_handles);
|
|
135
|
+
AE_procs = rb_ivar_get(mAsyncEngine, att_procs);
|
|
136
|
+
|
|
137
|
+
AE_ASSERT(AE_status == AE_STOPPED);
|
|
138
|
+
|
|
139
|
+
/* Load the UV idle (AE.next_tick) and UV async (AE.call_from_other_thread) now. */
|
|
140
|
+
load_ae_next_tick_uv_idle();
|
|
141
|
+
load_ae_call_from_other_thread();
|
|
142
|
+
|
|
143
|
+
/* Load the UV async for the ae_ubf() function. */
|
|
144
|
+
AE_ASSERT(ae_ubf_uv_async == NULL); // TODO: testing.
|
|
145
|
+
ae_ubf_uv_async = ALLOC(uv_async_t);
|
|
146
|
+
r = uv_async_init(AE_uv_loop, ae_ubf_uv_async, ae_ubf_uv_async_callback);
|
|
147
|
+
AE_ASSERT(r == 0);
|
|
148
|
+
|
|
149
|
+
/* Initial status. */
|
|
150
|
+
AE_status = AE_RUNNING;
|
|
151
|
+
|
|
152
|
+
/* Pass the given Proc to the reactor via next_tick. */
|
|
153
|
+
rb_funcall2(mAsyncEngine, method_next_tick, 1, &proc);
|
|
154
|
+
|
|
155
|
+
// TODO: for testing.
|
|
156
|
+
AE_ASSERT(ae_uv_num_active_reqs() == 0);
|
|
157
|
+
|
|
158
|
+
AE_DEBUG("UV loop starts...");
|
|
159
|
+
// uv_run() will block here until ae_release_loop() is called.
|
|
160
|
+
rb_thread_call_without_gvl(uv_run_without_gvl, NULL, ae_ubf, NULL);
|
|
161
|
+
AE_DEBUG("UV loop terminates");
|
|
162
|
+
|
|
163
|
+
// TODO: for testing.
|
|
164
|
+
AE_ASSERT(ae_uv_num_active_handlers() == 0);
|
|
165
|
+
AE_ASSERT(ae_uv_num_active_reqs() == 0);
|
|
166
|
+
|
|
167
|
+
// Unset the AE_uv_loop, AE_thread and AE_pid.
|
|
168
|
+
AE_uv_loop = NULL;
|
|
169
|
+
AE_thread = Qnil;
|
|
170
|
+
AE_pid = Qnil;
|
|
171
|
+
|
|
172
|
+
// Get the captured error in @_exit_error (if any) and clean @_exit_error.
|
|
173
|
+
captured_error = rb_ivar_get(mAsyncEngine, att_exit_error);
|
|
174
|
+
rb_ivar_set(mAsyncEngine, att_exit_error, Qnil);
|
|
175
|
+
|
|
176
|
+
// Now yes, set the status to AE_STOPPED.
|
|
177
|
+
AE_status = AE_STOPPED;
|
|
178
|
+
|
|
179
|
+
// Release the barrier lock.
|
|
180
|
+
rb_barrier_release(AE_barrier);
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
* Run the procs within @_on_exit_procs in order by passing the captured error
|
|
184
|
+
* (is any) as argument.
|
|
185
|
+
*/
|
|
186
|
+
on_exit_procs = rb_ivar_get(mAsyncEngine, att_on_exit_procs);
|
|
187
|
+
rb_ivar_set(mAsyncEngine, att_on_exit_procs, rb_ary_new());
|
|
188
|
+
for(i=0 ; i<RARRAY_LEN(on_exit_procs) ; i++) {
|
|
189
|
+
ae_proc_call_1(rb_ary_entry(on_exit_procs, i), captured_error);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
* If an exception/error has been captured by the exception manager, raise it now
|
|
194
|
+
* but just in case it's an Exception object. Thread#kill does not set the error
|
|
195
|
+
* to an Exception so Ruby will do the rest.
|
|
196
|
+
*/
|
|
197
|
+
if (! NIL_P(captured_error)) {
|
|
198
|
+
if (rb_obj_is_kind_of(captured_error, rb_eException) == Qtrue) {
|
|
199
|
+
AE_DEBUG2("raising captured error (class: %s)", rb_obj_classname(captured_error));
|
|
200
|
+
rb_funcall2(mKernel, method_raise, 1, &captured_error);
|
|
201
|
+
}
|
|
202
|
+
else
|
|
203
|
+
AE_DEBUG2("AsyncEngine thread killed by Thread#kill");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return Qtrue;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
static
|
|
211
|
+
VALUE uv_run_without_gvl(void)
|
|
212
|
+
{
|
|
213
|
+
AE_TRACE();
|
|
214
|
+
|
|
215
|
+
uv_run(AE_uv_loop);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
static
|
|
220
|
+
void ae_ubf(void)
|
|
221
|
+
{
|
|
222
|
+
AE_TRACE();
|
|
223
|
+
int r;
|
|
224
|
+
|
|
225
|
+
if (AE_status != AE_RUNNING)
|
|
226
|
+
return;
|
|
227
|
+
|
|
228
|
+
/*
|
|
229
|
+
* When a signal is received by a Ruby process running a blocking code (without GVL)
|
|
230
|
+
* Ruby calls the ubf() function. But this ubf() function could be called also from
|
|
231
|
+
* other thread (i.e. ae_tread.kill) so we don't know if the ubf() is being executing
|
|
232
|
+
* in AE thread, nor if it has been called due a received signal or a Thread#kill.
|
|
233
|
+
* Therefore, do nothing but check interrupts in Ruby land via a thread safe uv_async.
|
|
234
|
+
*/
|
|
235
|
+
|
|
236
|
+
r = uv_async_send(ae_ubf_uv_async);
|
|
237
|
+
AE_ASSERT(r == 0);
|
|
32
238
|
}
|
|
33
239
|
|
|
34
240
|
|
|
35
|
-
|
|
241
|
+
static
|
|
242
|
+
void ae_ubf_uv_async_callback(uv_async_t* handle, int status)
|
|
36
243
|
{
|
|
37
244
|
AE_TRACE();
|
|
38
|
-
uv_prepare_t *_uv_prepare = ALLOC(uv_prepare_t);
|
|
39
245
|
|
|
40
|
-
|
|
41
|
-
|
|
246
|
+
if (AE_status != AE_RUNNING)
|
|
247
|
+
return;
|
|
42
248
|
|
|
43
|
-
|
|
249
|
+
AE_DEBUG("ae_take_gvl_and_run_with_error_handler(rb_thread_check_ints)");
|
|
250
|
+
ae_take_gvl_and_run_with_error_handler(rb_thread_check_ints);
|
|
44
251
|
}
|
|
45
252
|
|
|
46
253
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
VALUE AsyncEngine_num_handles(VALUE self)
|
|
254
|
+
/** AE.release_loop private method. */
|
|
255
|
+
|
|
256
|
+
static
|
|
257
|
+
VALUE AsyncEngine_release_loop(VALUE self)
|
|
52
258
|
{
|
|
53
|
-
|
|
259
|
+
AE_TRACE();
|
|
260
|
+
|
|
261
|
+
ae_release_loop();
|
|
262
|
+
return Qnil;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
static
|
|
267
|
+
void ae_release_loop(void)
|
|
268
|
+
{
|
|
269
|
+
AE_TRACE();
|
|
270
|
+
|
|
271
|
+
/*
|
|
272
|
+
* Avoid this function to be called twice. When AE.stop is called it calls this method within
|
|
273
|
+
* a next_tick() or call_from_other_thread(), so when arriving here AE could already be
|
|
274
|
+
* releasing (by a previous AE.stop, exception or whatever).
|
|
275
|
+
*/
|
|
276
|
+
switch(AE_status) {
|
|
277
|
+
case AE_RUNNING:
|
|
278
|
+
break;
|
|
279
|
+
case AE_STOPPED:
|
|
280
|
+
AE_DEBUG("AE_status == AE_STOPPED, returning");
|
|
281
|
+
return;
|
|
282
|
+
break;
|
|
283
|
+
case AE_RELEASING:
|
|
284
|
+
AE_DEBUG("AE_status == AE_RELEASING, returning");
|
|
285
|
+
return;
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// No more handles can be created from now.
|
|
290
|
+
AE_status = AE_RELEASING;
|
|
291
|
+
|
|
292
|
+
// Clear @_next_tick_procs.
|
|
293
|
+
rb_ary_clear(rb_ivar_get(mAsyncEngine, att_next_tick_procs));
|
|
294
|
+
|
|
295
|
+
// Clear @_call_from_other_thread_procs.
|
|
296
|
+
rb_ary_clear(rb_ivar_get(mAsyncEngine, att_call_from_other_thread_procs));
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
* Run #destroy() for each existing AE handle. Note that #destroy() method
|
|
300
|
+
* is called safely in every AE handle by ignoring any exception/error.
|
|
301
|
+
* */
|
|
302
|
+
rb_hash_foreach(AE_handles, destroy_handle, Qnil);
|
|
303
|
+
|
|
304
|
+
/* Close AE internal handles. If the async handles are not closed uv_run() won't exit. */
|
|
305
|
+
unload_ae_next_tick_uv_idle();
|
|
306
|
+
unload_ae_call_from_other_thread();
|
|
307
|
+
AE_ASSERT(ae_ubf_uv_async != NULL); // TODO: testing.
|
|
308
|
+
AE_CLOSE_UV_HANDLE(ae_ubf_uv_async);
|
|
309
|
+
ae_ubf_uv_async = NULL;
|
|
310
|
+
|
|
311
|
+
// Clear @_procs.
|
|
312
|
+
rb_funcall2(AE_procs, method_clear, 0, NULL);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
static
|
|
317
|
+
int destroy_handle(VALUE key, VALUE handle, VALUE in)
|
|
318
|
+
{
|
|
319
|
+
AE_TRACE();
|
|
320
|
+
VALUE error;
|
|
321
|
+
int error_tag;
|
|
322
|
+
|
|
323
|
+
rb_protect(destroy_handle_with_rb_protect, handle, &error_tag);
|
|
324
|
+
if (error_tag) {
|
|
325
|
+
error = rb_errinfo();
|
|
326
|
+
rb_set_errinfo(Qnil);
|
|
327
|
+
AE_DEBUG2("error (class: %s) rescued with rb_protect() while destroying the handle", rb_obj_classname(error)); // TODO: for testing
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return 0;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
static
|
|
335
|
+
VALUE destroy_handle_with_rb_protect(VALUE handle)
|
|
336
|
+
{
|
|
337
|
+
AE_TRACE();
|
|
338
|
+
|
|
339
|
+
return rb_funcall2(handle, method_destroy, 0, NULL);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
/** AE.is_running? method. */
|
|
344
|
+
|
|
345
|
+
static
|
|
346
|
+
VALUE AsyncEngine_is_running(VALUE self)
|
|
347
|
+
{
|
|
348
|
+
AE_TRACE();
|
|
349
|
+
|
|
350
|
+
return (AE_status == AE_RUNNING ? Qtrue : Qfalse);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
/** ae_is_running_thread() and AE.is_running_thread methods. */
|
|
355
|
+
|
|
356
|
+
static
|
|
357
|
+
int ae_is_running_thread(void)
|
|
358
|
+
{
|
|
359
|
+
AE_TRACE();
|
|
360
|
+
|
|
361
|
+
return (rb_thread_current() == AE_thread ? 1 : 0);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
static
|
|
366
|
+
VALUE AsyncEngine_is_running_thread(VALUE self)
|
|
367
|
+
{
|
|
368
|
+
AE_TRACE();
|
|
369
|
+
|
|
370
|
+
return (ae_is_running_thread() ? Qtrue : Qfalse);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
/** ae_handle_error function. */
|
|
375
|
+
|
|
376
|
+
void ae_handle_error(VALUE error)
|
|
377
|
+
{
|
|
378
|
+
AE_TRACE();
|
|
379
|
+
VALUE error2;
|
|
380
|
+
int error_tag;
|
|
381
|
+
|
|
382
|
+
if ((! NIL_P(rb_ivar_get(mAsyncEngine, att_user_error_handler))) && rb_obj_is_kind_of(error, rb_eStandardError) == Qtrue) {
|
|
383
|
+
rb_protect(ae_handle_error_with_rb_protect, error, &error_tag);
|
|
384
|
+
if (error_tag) {
|
|
385
|
+
error2 = rb_errinfo();
|
|
386
|
+
rb_set_errinfo(Qnil);
|
|
387
|
+
AE_DEBUG2("error (class: %s) rescued with rb_protect() while running the user error handler", rb_obj_classname(error2)); // TODO: for testing
|
|
388
|
+
rb_ivar_set(mAsyncEngine, att_exit_error, error2);
|
|
389
|
+
ae_release_loop();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
AE_DEBUG2("error (class: %s) occurred with rb_protect(), releasing...", rb_obj_classname(error));
|
|
394
|
+
/*
|
|
395
|
+
* error could return Fixnum 8 when AE thread is killed with Thread#kill:
|
|
396
|
+
* https://github.com/ibc/AsyncEngine/issues/4
|
|
397
|
+
* In this case convert to Interrupt.
|
|
398
|
+
*/
|
|
399
|
+
if (FIXNUM_P(error))
|
|
400
|
+
error = rb_exc_new2(rb_eInterrupt, "Thread killed (AsyncEngine workaround for https://github.com/ibc/AsyncEngine/issues/4)");
|
|
401
|
+
|
|
402
|
+
rb_ivar_set(mAsyncEngine, att_exit_error, error);
|
|
403
|
+
ae_release_loop();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
static
|
|
409
|
+
VALUE ae_handle_error_with_rb_protect(VALUE error)
|
|
410
|
+
{
|
|
411
|
+
AE_TRACE();
|
|
412
|
+
|
|
413
|
+
return rb_funcall2(rb_ivar_get(mAsyncEngine, att_user_error_handler), method_call, 1, &error);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
/** AE.check_status method. */
|
|
418
|
+
|
|
419
|
+
static
|
|
420
|
+
VALUE AsyncEngine_check_status(VALUE self)
|
|
421
|
+
{
|
|
422
|
+
AE_TRACE();
|
|
423
|
+
|
|
424
|
+
AE_CHECK_STATUS();
|
|
425
|
+
return Qtrue;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
/** Function that generates AE::UV_ERRORS hash reading UV error list. */
|
|
430
|
+
|
|
431
|
+
static
|
|
432
|
+
VALUE generate_AE_UV_ERRORS_hash(void)
|
|
433
|
+
{
|
|
434
|
+
AE_TRACE();
|
|
435
|
+
VALUE hash = rb_hash_new();
|
|
436
|
+
VALUE uv_error;
|
|
437
|
+
VALUE args[3];
|
|
438
|
+
|
|
439
|
+
#define _AE_FILL_UV_ERRORS(val, name, s) \
|
|
440
|
+
args[0] = INT2FIX(val); \
|
|
441
|
+
args[1] = ID2SYM(rb_intern(#name)); \
|
|
442
|
+
args[2] = rb_str_new2(s); \
|
|
443
|
+
uv_error = rb_class_new_instance(3, args, eAsyncEngineUvError); \
|
|
444
|
+
rb_hash_aset(hash, INT2FIX(val), uv_error);
|
|
445
|
+
|
|
446
|
+
UV_ERRNO_MAP(_AE_FILL_UV_ERRORS)
|
|
447
|
+
#undef _AE_FILL_UV_ERRORS
|
|
448
|
+
|
|
449
|
+
return hash;
|
|
54
450
|
}
|
|
55
451
|
|
|
56
452
|
|
|
@@ -60,13 +456,60 @@ void Init_asyncengine_ext()
|
|
|
60
456
|
{
|
|
61
457
|
AE_TRACE();
|
|
62
458
|
|
|
459
|
+
mProcess = rb_define_module("Process");
|
|
460
|
+
mKernel = rb_define_module("Kernel");
|
|
461
|
+
|
|
63
462
|
mAsyncEngine = rb_define_module("AsyncEngine");
|
|
463
|
+
cAsyncEngineHandle = rb_define_class_under(mAsyncEngine, "Handle", rb_cObject);
|
|
464
|
+
eAsyncEngineError = rb_define_class_under(mAsyncEngine, "Error", rb_eStandardError);
|
|
465
|
+
eAsyncEngineUvError = rb_define_class_under(mAsyncEngine, "UvError", eAsyncEngineError);
|
|
466
|
+
eAsyncEngineNotRunningError = rb_define_class_under(mAsyncEngine, "NotRunningError", eAsyncEngineError);
|
|
467
|
+
|
|
468
|
+
rb_define_module_function(mAsyncEngine, "run", AsyncEngine_run, -1);
|
|
469
|
+
rb_define_module_function(mAsyncEngine, "release_loop", AsyncEngine_release_loop, 0);
|
|
470
|
+
rb_define_module_function(mAsyncEngine, "running?", AsyncEngine_is_running, 0);
|
|
471
|
+
rb_define_module_function(mAsyncEngine, "running_thread?", AsyncEngine_is_running_thread, 0);
|
|
472
|
+
rb_define_module_function(mAsyncEngine, "check_status", AsyncEngine_check_status, 0); // TODO: Should be removed since all will be in C.
|
|
473
|
+
// TODO: temporal methods (for debugging).
|
|
474
|
+
rb_define_module_function(mAsyncEngine, "num_uv_active_handles", AsyncEngine_num_uv_active_handles, 0);
|
|
475
|
+
rb_define_module_function(mAsyncEngine, "num_uv_active_reqs", AsyncEngine_num_uv_active_reqs, 0);
|
|
64
476
|
|
|
65
|
-
|
|
66
|
-
|
|
477
|
+
att_handles = rb_intern("@_handles");
|
|
478
|
+
att_procs = rb_intern("@_procs");
|
|
479
|
+
att_next_tick_procs = rb_intern("@_next_tick_procs");
|
|
480
|
+
att_call_from_other_thread_procs = rb_intern("@_call_from_other_thread_procs");
|
|
481
|
+
att_exit_error = rb_intern("@_exit_error");
|
|
482
|
+
att_user_error_handler = rb_intern("@_user_error_handler");
|
|
483
|
+
att_on_exit_procs = rb_intern("@_on_exit_procs");
|
|
67
484
|
|
|
485
|
+
method_destroy = rb_intern("destroy");
|
|
486
|
+
method_clear = rb_intern("clear");
|
|
487
|
+
method_next_tick = rb_intern("next_tick");
|
|
488
|
+
method_call_from_other_thread = rb_intern("call_from_other_thread");
|
|
489
|
+
method_pid = rb_intern("pid");
|
|
490
|
+
method_pid = rb_intern("pid");
|
|
491
|
+
method_raise = rb_intern("raise");
|
|
492
|
+
method_call = rb_intern("call");
|
|
493
|
+
|
|
494
|
+
init_rb_utilities();
|
|
68
495
|
init_ae_handle_common();
|
|
69
|
-
|
|
496
|
+
init_ae_utils();
|
|
497
|
+
init_ae_ip_utils();
|
|
498
|
+
init_ae_call_from_other_thread();
|
|
70
499
|
init_ae_next_tick();
|
|
500
|
+
init_ae_timer();
|
|
71
501
|
init_ae_udp();
|
|
72
|
-
|
|
502
|
+
init_ae_tcp();
|
|
503
|
+
init_ae_resolver();
|
|
504
|
+
|
|
505
|
+
ae_ubf_uv_async = NULL;
|
|
506
|
+
|
|
507
|
+
AE_UV_ERRORS = generate_AE_UV_ERRORS_hash();
|
|
508
|
+
rb_const_set(mAsyncEngine, rb_intern("UV_ERRORS"), AE_UV_ERRORS);
|
|
509
|
+
|
|
510
|
+
AE_barrier = rb_barrier_new();
|
|
511
|
+
rb_gc_register_address(&AE_barrier);
|
|
512
|
+
|
|
513
|
+
AE_uv_loop = NULL;
|
|
514
|
+
AE_status = AE_STOPPED;
|
|
515
|
+
}
|