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.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -0,0 +1,3 @@
1
+ # AsyncEngine
2
+
3
+ In development status. I won't write the README until AsyncEngine becomes robust, usable, full-featured and tested. And it will.
@@ -0,0 +1,38 @@
1
+ require "rake/testtask"
2
+ require "rake/clean"
3
+
4
+ AE_EXTEN_DIR = "ext/asyncengine"
5
+ AE_EXTEN_NAME_SO = "asyncengine_ext.so"
6
+ AE_LIB_SO = "lib/asyncengine/asyncengine_ext.so"
7
+
8
+ # Rule to build the extension: this says that the extension should be rebuilt
9
+ # after any change to the files in the extension dir.
10
+ file AE_LIB_SO =>
11
+ Dir.glob("#{AE_EXTEN_DIR}/*{.rb,.c,.h}") do
12
+ Dir.chdir(AE_EXTEN_DIR) do
13
+ ruby "extconf.rb"
14
+ sh "make"
15
+ end
16
+ cp "#{AE_EXTEN_DIR}/#{AE_EXTEN_NAME_SO}", AE_LIB_SO
17
+ end
18
+
19
+ # Use 'rake clean' and 'rake clobber' to easily delete generated files.
20
+ CLEAN.include("#{AE_EXTEN_DIR}/*{.o,.log,.so,.a}")
21
+ CLEAN.include("#{AE_EXTEN_DIR}/Makefile")
22
+ CLEAN.include(AE_LIB_SO)
23
+ CLOBBER.include("#{AE_EXTEN_DIR}/libuv/**/*{.o,.a}")
24
+
25
+
26
+ task :default => :compile
27
+
28
+ desc "Compile"
29
+ task :compile => AE_LIB_SO
30
+
31
+ Rake::TestTask.new do |t|
32
+ t.libs << "test"
33
+ end
34
+
35
+ # Make the :test task depend on the shared object, so it will be built automatically
36
+ # before running the tests.
37
+ desc "Run tests"
38
+ task :test => AE_LIB_SO
@@ -8,19 +8,23 @@ Gem::Specification.new do |spec|
8
8
  spec.date = Time.now
9
9
  spec.authors = ["Inaki Baz Castillo"]
10
10
  spec.email = "ibc@aliax.net"
11
- spec.summary = "Ruby asynchronous event driven library based on libuv"
11
+ spec.summary = "Ruby asynchronous event driven framework on top of libuv"
12
12
  spec.homepage = "https://github.com/ibc/AsyncEngine"
13
- spec.description = "Ruby asynchronous event driven library based on libuv"
14
- spec.extensions = ["ext/asyncengine/extconf.rb"]
13
+ spec.description = "Ruby asynchronous event driven framework on top of libuv"
15
14
  spec.required_ruby_version = ">= 1.9.2"
16
15
 
17
16
  files = %w{
18
17
  asyncengine.gemspec
18
+ Rakefile
19
19
  README.markdown
20
- lib/**/**
20
+ lib/**/**/**
21
21
  ext/asyncengine/{*.c,*.h,*.rb}
22
22
  ext/asyncengine/libuv/**/**/**/**/**/**/**/**/**
23
+ test/{ae_test_helper.rb}
24
+ test/{test_*.rb}
23
25
  }.join(",")
26
+
24
27
  spec.files = Dir.glob "{#{files}}"
25
28
  spec.require_paths = ["lib"]
29
+ spec.extensions = ["ext/asyncengine/extconf.rb"]
26
30
  end
@@ -0,0 +1,106 @@
1
+ #include "asyncengine_ruby.h"
2
+ #include "ae_handle_common.h"
3
+ #include "ae_call_from_other_thread.h"
4
+
5
+
6
+ static ID att_call_from_other_thread_procs;
7
+
8
+ static uv_async_t* ae_call_from_other_thread_uv_async;
9
+
10
+
11
+ /** Pre-declaration of static functions. */
12
+
13
+ static void _uv_async_callback(uv_async_t* handle, int status);
14
+ static VALUE _ae_async_callback(void);
15
+
16
+
17
+ void init_ae_call_from_other_thread(void)
18
+ {
19
+ AE_TRACE();
20
+
21
+ rb_define_module_function(mAsyncEngine, "call_from_other_thread", AsyncEngine_call_from_other_thread, -1);
22
+
23
+ att_call_from_other_thread_procs = rb_intern("@_call_from_other_thread_procs");
24
+
25
+ ae_call_from_other_thread_uv_async = NULL;
26
+ }
27
+
28
+
29
+ void load_ae_call_from_other_thread(void)
30
+ {
31
+ AE_TRACE();
32
+ int r;
33
+
34
+ AE_ASSERT(ae_call_from_other_thread_uv_async == NULL);
35
+
36
+ ae_call_from_other_thread_uv_async = ALLOC(uv_async_t);
37
+ r = uv_async_init(AE_uv_loop, ae_call_from_other_thread_uv_async, _uv_async_callback);
38
+ AE_ASSERT(r == 0);
39
+ }
40
+
41
+
42
+ void unload_ae_call_from_other_thread(void)
43
+ {
44
+ AE_TRACE();
45
+
46
+ AE_ASSERT(ae_call_from_other_thread_uv_async != NULL);
47
+
48
+ AE_CLOSE_UV_HANDLE(ae_call_from_other_thread_uv_async);
49
+ ae_call_from_other_thread_uv_async = NULL;
50
+ }
51
+
52
+
53
+ static
54
+ VALUE AsyncEngine_call_from_other_thread(int argc, VALUE *argv, VALUE self)
55
+ {
56
+ AE_TRACE();
57
+ VALUE proc;
58
+ int r;
59
+
60
+ AE_CHECK_STATUS();
61
+ AE_RB_CHECK_NUM_ARGS(0,1);
62
+ AE_RB_ENSURE_BLOCK_OR_PROC(1, proc);
63
+
64
+ rb_ary_push(rb_ivar_get(mAsyncEngine, att_call_from_other_thread_procs), proc);
65
+ r = uv_async_send(ae_call_from_other_thread_uv_async);
66
+ AE_ASSERT(r == 0);
67
+
68
+ return Qtrue;
69
+ }
70
+
71
+
72
+ static
73
+ void _uv_async_callback(uv_async_t* handle, int status)
74
+ {
75
+ AE_TRACE();
76
+
77
+ ae_take_gvl_and_run_with_error_handler(_ae_async_callback);
78
+ }
79
+
80
+
81
+ static
82
+ VALUE _ae_async_callback(void)
83
+ {
84
+ AE_TRACE();
85
+ VALUE procs;
86
+ long i;
87
+
88
+ AE_ASSERT(AE_status == AE_RUNNING);
89
+
90
+ // procs = @_call_from_other_thread_procs
91
+ procs = rb_ivar_get(mAsyncEngine, att_call_from_other_thread_procs);
92
+ // @_call_from_other_thread_procs = []
93
+ rb_ivar_set(mAsyncEngine, att_call_from_other_thread_procs, rb_ary_new());
94
+
95
+ // Iterate procs Array and call each proc.
96
+ for(i=0 ; i<RARRAY_LEN(procs) ; i++) {
97
+ // It could occur that one of these procs is a release_loop() method, so
98
+ // stop iterating.
99
+ if (AE_status != AE_RUNNING)
100
+ break;
101
+ ae_run_with_error_handler(ae_proc_call_0, rb_ary_entry(procs, i));
102
+ }
103
+ procs = Qnil;
104
+
105
+ return Qnil;
106
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef AE_CALL_FROM_OTHER_THREAD_H
2
+ #define AE_CALL_FROM_OTHER_THREAD_H
3
+
4
+
5
+ void init_ae_call_from_other_thread(void);
6
+ void load_ae_call_from_other_thread_uv_async(void);
7
+ void unload_ae_call_from_other_thread_uv_async(void);
8
+
9
+ static VALUE AsyncEngine_call_from_other_thread(int argc, VALUE *argv, VALUE self);
10
+
11
+
12
+ #endif /* AE_CALL_FROM_OTHER_THREAD_H */
@@ -2,99 +2,244 @@
2
2
  #include "ae_handle_common.h"
3
3
 
4
4
 
5
- // Global variables defined in asyncengine_ruby.c.
6
- extern VALUE mAsyncEngine;
5
+ // Ruby modules/classes.
6
+ static VALUE mKernel;
7
7
 
8
- // C variable holding current block number.
9
- static long block_id = 0;
8
+ // Ruby method names.
9
+ static ID method_call;
10
+ static ID method_handle_error;
11
+ static ID method_raise;
10
12
 
11
- // Ruby class for saving C data inside.
12
- VALUE cAsyncEngineCData;
13
+ // C variable holding current proc number.
14
+ static long proc_long_id;
13
15
 
14
- // Ruby attributes.
15
- static ID att_blocks;
16
- ID att_cdata;
17
- ID att_handle_terminated;
18
16
 
19
- // Ruby method names.
20
- ID id_method_call;
21
- ID id_manage_exception;
17
+ void init_ae_handle_common(void)
18
+ {
19
+ AE_TRACE();
20
+
21
+ mKernel = rb_define_module("Kernel");
22
+
23
+ method_call = rb_intern("call");
24
+ method_handle_error = rb_intern("handle_error");
25
+ method_raise = rb_intern("raise");
26
+
27
+ proc_long_id = 0;
28
+ }
22
29
 
23
30
 
24
- void init_ae_handle_common()
31
+ VALUE ae_store_handle(VALUE ae_handle)
25
32
  {
26
- cAsyncEngineCData = rb_define_class_under(mAsyncEngine, "CData", rb_cObject);
33
+ AE_TRACE();
27
34
 
28
- att_blocks = rb_intern("@_blocks");
29
- att_cdata = rb_intern("@_cdata");
30
- att_handle_terminated = rb_intern("@_handle_terminated");
35
+ VALUE ae_handle_id = rb_obj_id(ae_handle);
36
+ rb_hash_aset(AE_handles, ae_handle_id, ae_handle);
31
37
 
32
- id_method_call = rb_intern("call");
33
- id_manage_exception = rb_intern("manage_exception");
38
+ return ae_handle_id;
34
39
  }
35
40
 
36
41
 
37
- VALUE ae_store_block(VALUE block)
42
+ VALUE ae_get_handle(VALUE ae_handle_id)
38
43
  {
39
44
  AE_TRACE();
40
- VALUE rb_block_id = LONG2FIX(++block_id);
41
45
 
42
- rb_hash_aset(rb_ivar_get(mAsyncEngine, att_blocks), rb_block_id, block);
43
- return rb_block_id;
46
+ return rb_hash_aref(AE_handles, ae_handle_id);
44
47
  }
45
48
 
46
49
 
47
- VALUE ae_get_block(VALUE rb_block_id)
50
+ VALUE ae_remove_handle(VALUE ae_handle_id)
48
51
  {
49
52
  AE_TRACE();
50
- return rb_hash_aref(rb_ivar_get(mAsyncEngine, att_blocks), rb_block_id);
53
+
54
+ return rb_hash_delete(AE_handles, ae_handle_id);
51
55
  }
52
56
 
53
57
 
54
- VALUE ae_remove_block(VALUE rb_block_id)
58
+ VALUE ae_store_proc(VALUE proc)
55
59
  {
56
60
  AE_TRACE();
57
- return rb_hash_delete(rb_ivar_get(mAsyncEngine, att_blocks), rb_block_id);
61
+
62
+ VALUE proc_id = LONG2FIX(++proc_long_id);
63
+ rb_hash_aset(AE_procs, proc_id, proc);
64
+
65
+ return proc_id;
58
66
  }
59
67
 
60
68
 
61
- void ae_manage_exception(int exception_tag)
69
+ VALUE ae_get_proc(VALUE proc_id)
62
70
  {
63
71
  AE_TRACE();
64
72
 
65
- // rb_errinfo() gives the current exception object in this thread.
66
- VALUE exception = rb_errinfo();
73
+ return rb_hash_aref(AE_procs, proc_id);
74
+ }
67
75
 
68
- // Just check the exception in the user provided AE.exception_manager block if
69
- // it is a StandardError. Otherwise raise it and terminate.
70
- if (rb_obj_is_kind_of(exception, rb_eStandardError) == Qtrue) {
71
- rb_funcall(mAsyncEngine, id_manage_exception, 1, exception);
72
- // Dissable the current thread exception.
73
- rb_set_errinfo(Qnil);
74
- }
75
- else
76
- rb_jump_tag(exception_tag);
76
+
77
+ VALUE ae_remove_proc(VALUE proc_id)
78
+ {
79
+ AE_TRACE();
80
+
81
+ return rb_hash_delete(AE_procs, proc_id);
77
82
  }
78
83
 
79
84
 
80
- void ae_handle_close_callback_0(uv_handle_t* handle)
85
+ void ae_uv_handle_close_callback(uv_handle_t* handle)
81
86
  {
82
87
  AE_TRACE();
88
+
83
89
  xfree(handle);
84
90
  }
85
91
 
86
92
 
87
- static VALUE wrapper_rb_funcall_0(VALUE block)
93
+ int ae_get_last_uv_error_int(void)
94
+ {
95
+ AE_TRACE();
96
+
97
+ return uv_last_error(AE_uv_loop).code;
98
+ }
99
+
100
+
101
+ VALUE ae_get_uv_error(int uv_errno)
102
+ {
103
+ AE_TRACE();
104
+
105
+ VALUE ae_uv_error;
106
+
107
+ if (NIL_P(ae_uv_error = rb_hash_aref(AE_UV_ERRORS, INT2FIX(uv_errno))))
108
+ ae_uv_error = rb_hash_aref(AE_UV_ERRORS, INT2FIX(-1));
109
+
110
+ return ae_uv_error;
111
+ }
112
+
113
+
114
+ VALUE ae_get_last_uv_error(void)
115
+ {
116
+ AE_TRACE();
117
+
118
+ VALUE ae_uv_error;
119
+
120
+ if (NIL_P(ae_uv_error = rb_hash_aref(AE_UV_ERRORS, INT2FIX(uv_last_error(AE_uv_loop).code))))
121
+ ae_uv_error = rb_hash_aref(AE_UV_ERRORS, INT2FIX(-1));
122
+
123
+ return ae_uv_error;
124
+ }
125
+
126
+
127
+ void ae_raise_uv_error(int uv_errno)
128
+ {
129
+ AE_TRACE();
130
+
131
+ VALUE ae_uv_error = ae_get_uv_error(uv_errno);
132
+
133
+ rb_funcall2(mKernel, method_raise, 1, &ae_uv_error);
134
+ }
135
+
136
+
137
+ void ae_raise_last_uv_error(void)
88
138
  {
89
- rb_funcall(block, id_method_call, 0, 0);
90
- return Qnil;
139
+ AE_TRACE();
140
+
141
+ VALUE ae_uv_error = ae_get_last_uv_error();
142
+
143
+ rb_funcall2(mKernel, method_raise, 1, &ae_uv_error);
91
144
  }
92
145
 
93
146
 
94
- int ae_protect_block_call_0(VALUE block)
147
+ VALUE ae_proc_call_0(VALUE proc)
95
148
  {
96
- int exception = 0;
149
+ AE_TRACE();
97
150
 
98
- rb_protect(wrapper_rb_funcall_0, block, &exception);
99
- return exception;
151
+ AE_ASSERT(! NIL_P(proc));
152
+ return rb_funcall2(proc, method_call, 0, NULL);
100
153
  }
154
+
155
+
156
+ VALUE ae_proc_call_1(VALUE proc, VALUE param)
157
+ {
158
+ AE_TRACE();
159
+
160
+ AE_ASSERT(! NIL_P(proc));
161
+ return rb_funcall2(proc, method_call, 1, &param);
162
+ }
163
+
164
+
165
+ VALUE ae_proc_call_2(VALUE proc, VALUE param1, VALUE param2)
166
+ {
167
+ AE_TRACE();
168
+
169
+ AE_ASSERT(! NIL_P(proc));
170
+ return rb_funcall(proc, method_call, 2, param1, param2);
171
+ }
172
+
173
+
174
+ VALUE ae_proc_call_3(VALUE proc, VALUE param1, VALUE param2, VALUE param3)
175
+ {
176
+ AE_TRACE();
177
+
178
+ AE_ASSERT(! NIL_P(proc));
179
+ return rb_funcall(proc, method_call, 3, param1, param2, param3);
180
+ }
181
+
182
+
183
+ /*
184
+ * When any AsyncEngine handler runs a handle method having the GVL,
185
+ * it must use this function, which can receive an optional VALUE parameter.
186
+ */
187
+ VALUE ae_run_with_error_handler(void* function, VALUE param)
188
+ {
189
+ AE_TRACE();
190
+
191
+ VALUE ret, error;
192
+ int error_tag;
193
+
194
+ if (param)
195
+ ret = rb_protect(function, (VALUE)param, &error_tag);
196
+ else
197
+ ret = rb_protect(function, Qnil, &error_tag);
198
+
199
+ /*
200
+ * If an error occurs while in function() it can be due:
201
+ *
202
+ * - An Exception (including SystemExit), this is "rescue-able" via "rescue Exception"
203
+ * and will run the "ensure" code if present. In this case rb_errinfo() returns the
204
+ * exact Exception object.
205
+ *
206
+ * - A Thread#kill. This is NOT "rescue-able" via "rescue Exception" but it WILL run
207
+ * the "ensure" code if present. In this case rb_errinfo() returns FIXNUM 8.
208
+ *
209
+ * So, check the class of the object returned by rb_errinfo(). If it's an Exception then
210
+ * store it, release the loop and raise it. Otherwise (Thread#kill) then don't store the
211
+ * exception returned by rb_errinfo() and just release the loop. Ruby will do the rest.
212
+ */
213
+
214
+ if (error_tag) {
215
+ // TODO: This could return Fixnum 8: https://github.com/ibc/AsyncEngine/issues/4,
216
+ // so the error handler must check it. Maybe it's better to set error=Qnil and
217
+ // pass it to the error handler? NO, let's ae_handle_error(error) to do it.
218
+ error = rb_errinfo();
219
+ rb_set_errinfo(Qnil);
220
+ AE_DEBUG("error class: %s", rb_obj_classname(error));
221
+
222
+ // NOTE: This function should never been called when releasing.
223
+ if (AE_status == AE_RELEASING)
224
+ AE_ABORT("error (class: %s) rescued while in releasing status", rb_obj_classname(error)); // TODO: testing, not sure yet.
225
+
226
+ AE_DEBUG("error (class: %s) rescued, passing it to the error handler", rb_obj_classname(error));
227
+ ae_handle_error(error);
228
+ return Qnil;
229
+ }
230
+ else
231
+ return ret;
232
+ }
233
+
234
+
235
+ /*
236
+ * When any AsyncEngine handler runs a Ruby callback, it must
237
+ * use this function, which must be called without the GVL.
238
+ * TODO: Allow passing a VALUE parameter...?
239
+ */
240
+ VALUE ae_take_gvl_and_run_with_error_handler(void* function)
241
+ {
242
+ AE_TRACE();
243
+
244
+ return rb_thread_call_with_gvl(ae_run_with_error_handler, function);
245
+ }