grpc 0.14.1 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (277) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1398 -817
  3. data/include/grpc/compression.h +2 -1
  4. data/include/grpc/grpc.h +10 -1
  5. data/include/grpc/grpc_cronet.h +51 -0
  6. data/include/grpc/grpc_posix.h +70 -0
  7. data/include/grpc/impl/codegen/atm.h +2 -2
  8. data/include/grpc/impl/codegen/{atm_win32.h → atm_windows.h} +3 -3
  9. data/include/grpc/impl/codegen/compression_types.h +39 -5
  10. data/include/grpc/impl/codegen/connectivity_state.h +1 -1
  11. data/include/grpc/impl/codegen/grpc_types.h +10 -0
  12. data/include/grpc/impl/codegen/log.h +2 -1
  13. data/include/grpc/impl/codegen/port_platform.h +30 -12
  14. data/include/grpc/impl/codegen/slice_buffer.h +2 -3
  15. data/include/grpc/impl/codegen/sync.h +2 -2
  16. data/include/grpc/impl/codegen/{sync_win32.h → sync_windows.h} +3 -3
  17. data/include/grpc/support/{sync_win32.h → atm_windows.h} +4 -4
  18. data/include/grpc/support/avl.h +5 -0
  19. data/include/grpc/support/{log_win32.h → log_windows.h} +3 -3
  20. data/include/grpc/support/string_util.h +2 -1
  21. data/include/grpc/support/{atm_win32.h → sync_windows.h} +4 -4
  22. data/src/core/ext/census/gen/census.pb.c +179 -0
  23. data/src/core/ext/census/gen/census.pb.h +294 -0
  24. data/src/core/ext/census/grpc_filter.c +11 -7
  25. data/src/core/ext/client_config/channel_connectivity.c +28 -14
  26. data/src/core/ext/client_config/client_channel.c +77 -53
  27. data/src/core/ext/client_config/connector.h +1 -1
  28. data/src/core/ext/client_config/lb_policy.c +9 -6
  29. data/src/core/ext/client_config/lb_policy.h +9 -5
  30. data/src/core/ext/client_config/subchannel.c +58 -39
  31. data/src/core/ext/client_config/subchannel.h +3 -2
  32. data/src/core/ext/client_config/subchannel_call_holder.c +34 -19
  33. data/src/core/ext/client_config/subchannel_call_holder.h +2 -1
  34. data/src/core/ext/client_config/subchannel_index.c +20 -9
  35. data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +7 -7
  36. data/src/core/ext/lb_policy/grpclb/load_balancer_api.h +5 -5
  37. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/{v0 → v1}/load_balancer.pb.c +29 -30
  38. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +178 -0
  39. data/src/core/ext/lb_policy/pick_first/pick_first.c +65 -45
  40. data/src/core/ext/lb_policy/round_robin/round_robin.c +84 -43
  41. data/src/core/ext/load_reporting/load_reporting.c +133 -0
  42. data/src/core/ext/load_reporting/load_reporting.h +75 -0
  43. data/src/core/ext/load_reporting/load_reporting_filter.c +151 -0
  44. data/src/core/ext/load_reporting/load_reporting_filter.h +41 -0
  45. data/src/core/ext/resolver/dns/native/dns_resolver.c +22 -8
  46. data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +2 -2
  47. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +4 -4
  48. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c +95 -0
  49. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +14 -18
  50. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +49 -24
  51. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c +82 -0
  52. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +104 -60
  53. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +232 -0
  54. data/src/{ruby/ext/grpc/rb_signal.c → core/ext/transport/chttp2/transport/bin_decoder.h} +27 -31
  55. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +481 -260
  56. data/src/core/ext/transport/chttp2/transport/frame.h +1 -7
  57. data/src/core/ext/transport/chttp2/transport/frame_data.c +44 -27
  58. data/src/core/ext/transport/chttp2/transport/frame_data.h +6 -5
  59. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +23 -17
  60. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +2 -2
  61. data/src/core/ext/transport/chttp2/transport/frame_ping.c +12 -7
  62. data/src/core/ext/transport/chttp2/transport/frame_ping.h +3 -3
  63. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +25 -12
  64. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +2 -2
  65. data/src/core/ext/transport/chttp2/transport/frame_settings.c +23 -21
  66. data/src/core/ext/transport/chttp2/transport/frame_settings.h +2 -2
  67. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +17 -9
  68. data/src/core/ext/transport/chttp2/transport/frame_window_update.h +2 -2
  69. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +365 -287
  70. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +8 -6
  71. data/src/core/ext/transport/chttp2/transport/hpack_table.c +24 -20
  72. data/src/core/ext/transport/chttp2/transport/hpack_table.h +5 -4
  73. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +1 -0
  74. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +1 -0
  75. data/src/core/ext/transport/chttp2/transport/internal.h +34 -32
  76. data/src/core/ext/transport/chttp2/transport/parsing.c +296 -212
  77. data/src/core/ext/transport/chttp2/transport/writing.c +12 -9
  78. data/src/core/lib/channel/channel_args.c +26 -12
  79. data/src/core/lib/channel/channel_args.h +1 -1
  80. data/src/core/lib/channel/channel_stack.c +12 -8
  81. data/src/core/lib/channel/channel_stack.h +27 -11
  82. data/src/core/lib/channel/channel_stack_builder.c +2 -2
  83. data/src/core/lib/channel/compress_filter.c +26 -31
  84. data/src/core/lib/channel/compress_filter.h +4 -4
  85. data/src/core/lib/channel/connected_channel.c +7 -5
  86. data/src/core/lib/channel/http_client_filter.c +34 -8
  87. data/src/core/lib/channel/http_client_filter.h +1 -1
  88. data/src/core/lib/channel/http_server_filter.c +21 -12
  89. data/src/core/lib/compression/{compression_algorithm.c → compression.c} +22 -21
  90. data/src/core/lib/http/httpcli.c +81 -59
  91. data/src/core/lib/http/httpcli.h +11 -15
  92. data/src/core/lib/http/httpcli_security_connector.c +5 -3
  93. data/src/core/lib/http/parser.c +127 -118
  94. data/src/core/lib/http/parser.h +11 -6
  95. data/src/core/lib/iomgr/closure.c +20 -16
  96. data/src/core/lib/iomgr/closure.h +19 -15
  97. data/src/core/lib/iomgr/endpoint.h +1 -1
  98. data/src/core/lib/iomgr/endpoint_pair_posix.c +2 -2
  99. data/src/core/lib/iomgr/error.c +535 -0
  100. data/src/core/lib/iomgr/error.h +192 -0
  101. data/src/core/lib/iomgr/ev_poll_and_epoll_posix.c +190 -83
  102. data/src/core/lib/iomgr/ev_poll_posix.c +1267 -0
  103. data/src/{ruby/ext/grpc/rb_signal.h → core/lib/iomgr/ev_poll_posix.h} +7 -5
  104. data/src/core/lib/iomgr/ev_posix.c +104 -14
  105. data/src/core/lib/iomgr/ev_posix.h +17 -7
  106. data/src/core/lib/iomgr/exec_ctx.c +25 -7
  107. data/src/core/lib/iomgr/exec_ctx.h +27 -8
  108. data/src/core/lib/iomgr/executor.c +2 -2
  109. data/src/core/lib/iomgr/executor.h +1 -1
  110. data/src/core/lib/iomgr/iocp_windows.c +2 -41
  111. data/src/core/lib/iomgr/iocp_windows.h +0 -8
  112. data/src/core/lib/iomgr/iomgr.c +5 -4
  113. data/src/core/lib/iomgr/iomgr_posix.c +5 -1
  114. data/src/core/lib/iomgr/iomgr_windows.c +1 -1
  115. data/src/core/lib/{support → iomgr}/load_file.c +15 -17
  116. data/src/core/lib/{support → iomgr}/load_file.h +8 -7
  117. data/src/core/lib/iomgr/polling_entity.c +104 -0
  118. data/src/core/lib/iomgr/polling_entity.h +81 -0
  119. data/src/core/lib/iomgr/pollset.h +6 -5
  120. data/src/core/lib/iomgr/pollset_set_windows.c +4 -1
  121. data/src/core/lib/iomgr/pollset_windows.c +10 -6
  122. data/src/core/lib/iomgr/resolve_address.h +5 -9
  123. data/src/core/lib/iomgr/resolve_address_posix.c +55 -38
  124. data/src/core/lib/iomgr/resolve_address_windows.c +51 -37
  125. data/src/core/lib/iomgr/sockaddr.h +2 -2
  126. data/src/core/lib/iomgr/{sockaddr_win32.h → sockaddr_windows.h} +3 -3
  127. data/src/core/lib/iomgr/socket_utils_common_posix.c +92 -45
  128. data/src/core/lib/iomgr/socket_utils_posix.h +19 -12
  129. data/src/core/lib/iomgr/socket_windows.c +61 -2
  130. data/src/core/lib/iomgr/socket_windows.h +13 -0
  131. data/src/core/lib/iomgr/tcp_client_posix.c +54 -39
  132. data/src/core/lib/iomgr/tcp_client_windows.c +34 -34
  133. data/src/core/lib/iomgr/tcp_posix.c +43 -39
  134. data/src/core/lib/iomgr/tcp_server.h +5 -3
  135. data/src/core/lib/iomgr/tcp_server_posix.c +103 -64
  136. data/src/core/lib/iomgr/tcp_server_windows.c +114 -101
  137. data/src/core/lib/iomgr/tcp_windows.c +45 -50
  138. data/src/core/lib/iomgr/tcp_windows.h +1 -1
  139. data/src/core/lib/iomgr/timer.c +26 -13
  140. data/src/core/lib/iomgr/udp_server.c +28 -4
  141. data/src/core/lib/iomgr/udp_server.h +5 -1
  142. data/src/core/lib/iomgr/unix_sockets_posix.c +8 -7
  143. data/src/core/lib/iomgr/unix_sockets_posix.h +2 -1
  144. data/src/core/lib/iomgr/unix_sockets_posix_noop.c +4 -2
  145. data/src/core/lib/iomgr/wakeup_fd_eventfd.c +15 -5
  146. data/src/core/lib/iomgr/wakeup_fd_pipe.c +13 -9
  147. data/src/core/lib/iomgr/wakeup_fd_posix.c +6 -6
  148. data/src/core/lib/iomgr/wakeup_fd_posix.h +9 -6
  149. data/src/core/lib/iomgr/workqueue.h +5 -4
  150. data/src/core/lib/iomgr/workqueue_posix.c +40 -26
  151. data/src/core/lib/iomgr/workqueue_windows.c +2 -2
  152. data/src/core/lib/profiling/basic_timers.c +2 -2
  153. data/src/core/lib/security/{security_context.c → context/security_context.c} +1 -1
  154. data/src/core/lib/security/{security_context.h → context/security_context.h} +4 -4
  155. data/src/core/lib/security/credentials/composite/composite_credentials.c +263 -0
  156. data/src/core/lib/security/credentials/composite/composite_credentials.h +72 -0
  157. data/src/core/lib/security/credentials/credentials.c +233 -0
  158. data/src/core/lib/security/{credentials.h → credentials/credentials.h} +19 -157
  159. data/src/core/lib/security/{credentials_metadata.c → credentials/credentials_metadata.c} +1 -1
  160. data/src/core/lib/security/credentials/fake/fake_credentials.c +139 -0
  161. data/src/core/lib/security/credentials/fake/fake_credentials.h +56 -0
  162. data/src/core/lib/security/{credentials_posix.c → credentials/google_default/credentials_posix.c} +1 -1
  163. data/src/core/lib/security/{credentials_win32.c → credentials/google_default/credentials_windows.c} +3 -3
  164. data/src/core/lib/security/{google_default_credentials.c → credentials/google_default/google_default_credentials.c} +93 -35
  165. data/src/core/lib/security/credentials/google_default/google_default_credentials.h +46 -0
  166. data/src/core/lib/security/credentials/iam/iam_credentials.c +85 -0
  167. data/src/core/lib/security/credentials/iam/iam_credentials.h +44 -0
  168. data/src/core/lib/security/{json_token.c → credentials/jwt/json_token.c} +10 -101
  169. data/src/core/lib/security/{json_token.h → credentials/jwt/json_token.h} +3 -33
  170. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +160 -0
  171. data/src/core/lib/security/credentials/jwt/jwt_credentials.h +62 -0
  172. data/src/core/lib/security/{jwt_verifier.c → credentials/jwt/jwt_verifier.c} +35 -15
  173. data/src/core/lib/security/{jwt_verifier.h → credentials/jwt/jwt_verifier.h} +3 -3
  174. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +433 -0
  175. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +109 -0
  176. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +129 -0
  177. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +45 -0
  178. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +240 -0
  179. data/src/core/lib/security/credentials/ssl/ssl_credentials.h +48 -0
  180. data/src/core/lib/security/{auth_filters.h → transport/auth_filters.h} +3 -3
  181. data/src/core/lib/security/{client_auth_filter.c → transport/client_auth_filter.c} +27 -20
  182. data/src/core/lib/security/{handshake.c → transport/handshake.c} +77 -45
  183. data/src/core/lib/security/{handshake.h → transport/handshake.h} +9 -11
  184. data/src/core/lib/security/{secure_endpoint.c → transport/secure_endpoint.c} +19 -12
  185. data/src/core/lib/security/{secure_endpoint.h → transport/secure_endpoint.h} +3 -3
  186. data/src/core/lib/security/{security_connector.c → transport/security_connector.c} +26 -17
  187. data/src/core/lib/security/{security_connector.h → transport/security_connector.h} +8 -8
  188. data/src/core/lib/security/{server_auth_filter.c → transport/server_auth_filter.c} +24 -16
  189. data/src/core/lib/security/transport/tsi_error.c +40 -0
  190. data/src/core/lib/security/transport/tsi_error.h +42 -0
  191. data/src/core/lib/security/{b64.c → util/b64.c} +1 -1
  192. data/src/core/lib/security/{b64.h → util/b64.h} +3 -3
  193. data/src/core/lib/security/util/json_util.c +61 -0
  194. data/src/core/lib/security/util/json_util.h +55 -0
  195. data/src/core/lib/support/avl.c +11 -0
  196. data/src/core/lib/support/cpu_windows.c +2 -2
  197. data/src/core/lib/support/{env_win32.c → env_windows.c} +3 -3
  198. data/src/core/lib/support/log.c +3 -1
  199. data/src/core/lib/support/log_linux.c +2 -2
  200. data/src/core/lib/support/{log_win32.c → log_windows.c} +4 -4
  201. data/src/core/lib/support/murmur_hash.c +3 -5
  202. data/src/core/lib/support/string.c +10 -0
  203. data/src/core/lib/support/string.h +4 -0
  204. data/src/core/lib/support/{string_util_win32.c → string_util_windows.c} +3 -3
  205. data/src/core/lib/support/{string_win32.c → string_windows.c} +2 -2
  206. data/src/core/lib/support/{string_win32.h → string_windows.h} +5 -5
  207. data/src/core/lib/support/subprocess_windows.c +1 -1
  208. data/src/core/lib/support/{sync_win32.c → sync_windows.c} +2 -2
  209. data/src/core/lib/support/{thd_win32.c → thd_windows.c} +2 -2
  210. data/src/core/lib/support/{time_win32.c → time_windows.c} +2 -2
  211. data/src/core/lib/support/tmpfile_msys.c +1 -1
  212. data/src/core/lib/support/{tmpfile_win32.c → tmpfile_windows.c} +3 -3
  213. data/src/core/lib/surface/alarm.c +2 -2
  214. data/src/core/lib/surface/byte_buffer_reader.c +13 -6
  215. data/src/core/lib/surface/call.c +323 -123
  216. data/src/core/lib/surface/call.h +2 -0
  217. data/src/core/lib/surface/call_log_batch.c +1 -1
  218. data/src/core/lib/surface/channel.c +64 -15
  219. data/src/core/lib/surface/channel.h +9 -0
  220. data/src/core/lib/surface/channel_ping.c +3 -3
  221. data/src/core/lib/surface/completion_queue.c +75 -19
  222. data/src/core/lib/surface/completion_queue.h +7 -2
  223. data/src/core/lib/surface/init.c +2 -1
  224. data/src/core/lib/surface/init_secure.c +4 -4
  225. data/src/core/lib/surface/lame_client.c +12 -8
  226. data/src/core/lib/surface/server.c +213 -120
  227. data/src/core/lib/surface/server.h +1 -0
  228. data/src/core/lib/surface/version.c +1 -1
  229. data/src/core/lib/transport/connectivity_state.c +40 -18
  230. data/src/core/lib/transport/connectivity_state.h +4 -1
  231. data/src/core/lib/transport/metadata.c +23 -23
  232. data/src/core/lib/transport/metadata.h +4 -0
  233. data/src/core/lib/transport/metadata_batch.c +9 -0
  234. data/src/core/lib/transport/metadata_batch.h +3 -0
  235. data/src/core/lib/transport/static_metadata.c +6 -5
  236. data/src/core/lib/transport/static_metadata.h +64 -60
  237. data/src/core/lib/transport/transport.c +24 -12
  238. data/src/core/lib/transport/transport.h +6 -5
  239. data/src/core/lib/transport/transport_impl.h +4 -0
  240. data/src/core/lib/transport/transport_op_string.c +2 -2
  241. data/src/core/plugin_registry/grpc_plugin_registry.c +4 -0
  242. data/src/ruby/bin/math_services.rb +41 -2
  243. data/src/ruby/ext/grpc/rb_call.c +42 -40
  244. data/src/ruby/ext/grpc/rb_channel.c +1 -1
  245. data/src/ruby/ext/grpc/rb_completion_queue.c +59 -6
  246. data/src/ruby/ext/grpc/rb_completion_queue.h +1 -1
  247. data/src/ruby/ext/grpc/rb_grpc.c +1 -3
  248. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +12 -2
  249. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +21 -5
  250. data/src/ruby/ext/grpc/rb_loader.c +1 -1
  251. data/src/ruby/ext/grpc/rb_server.c +5 -3
  252. data/src/ruby/lib/grpc.rb +0 -3
  253. data/src/ruby/lib/grpc/errors.rb +3 -2
  254. data/src/ruby/lib/grpc/generic/active_call.rb +32 -42
  255. data/src/ruby/lib/grpc/generic/bidi_call.rb +20 -0
  256. data/src/ruby/lib/grpc/generic/client_stub.rb +31 -54
  257. data/src/ruby/lib/grpc/generic/rpc_desc.rb +4 -4
  258. data/src/ruby/lib/grpc/generic/rpc_server.rb +12 -23
  259. data/src/ruby/lib/grpc/generic/service.rb +8 -8
  260. data/src/ruby/lib/grpc/version.rb +1 -1
  261. data/src/ruby/pb/grpc/health/v1/health_services.rb +30 -2
  262. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services.rb +34 -4
  263. data/src/ruby/pb/grpc/testing/metrics_services.rb +39 -2
  264. data/src/ruby/pb/src/proto/grpc/testing/empty.rb +15 -0
  265. data/src/ruby/pb/src/proto/grpc/testing/messages.rb +84 -0
  266. data/src/ruby/pb/src/proto/grpc/testing/test.rb +14 -0
  267. data/src/ruby/pb/src/proto/grpc/testing/test_services.rb +110 -0
  268. data/src/ruby/pb/test/client.rb +5 -2
  269. data/src/ruby/spec/generic/active_call_spec.rb +3 -2
  270. data/src/ruby/spec/generic/client_stub_spec.rb +27 -24
  271. data/src/ruby/spec/generic/rpc_desc_spec.rb +11 -11
  272. data/src/ruby/spec/generic/rpc_server_spec.rb +42 -61
  273. data/src/ruby/spec/pb/health/checker_spec.rb +3 -5
  274. metadata +86 -48
  275. data/src/core/ext/lb_policy/grpclb/proto/grpc/lb/v0/load_balancer.pb.h +0 -182
  276. data/src/core/lib/security/credentials.c +0 -1296
  277. data/src/ruby/lib/grpc/signals.rb +0 -69
@@ -60,7 +60,7 @@ void grpc_stream_unref(grpc_exec_ctx *exec_ctx,
60
60
  grpc_stream_refcount *refcount) {
61
61
  #endif
62
62
  if (gpr_unref(&refcount->refs)) {
63
- grpc_exec_ctx_enqueue(exec_ctx, &refcount->destroy, true, NULL);
63
+ grpc_exec_ctx_sched(exec_ctx, &refcount->destroy, GRPC_ERROR_NONE, NULL);
64
64
  }
65
65
  }
66
66
 
@@ -125,10 +125,19 @@ void grpc_transport_perform_op(grpc_exec_ctx *exec_ctx,
125
125
  transport->vtable->perform_op(exec_ctx, transport, op);
126
126
  }
127
127
 
128
- void grpc_transport_set_pollset(grpc_exec_ctx *exec_ctx,
129
- grpc_transport *transport, grpc_stream *stream,
130
- grpc_pollset *pollset) {
131
- transport->vtable->set_pollset(exec_ctx, transport, stream, pollset);
128
+ void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport,
129
+ grpc_stream *stream,
130
+ grpc_polling_entity *pollent) {
131
+ grpc_pollset *pollset;
132
+ grpc_pollset_set *pollset_set;
133
+ if ((pollset = grpc_polling_entity_pollset(pollent)) != NULL) {
134
+ transport->vtable->set_pollset(exec_ctx, transport, stream, pollset);
135
+ } else if ((pollset_set = grpc_polling_entity_pollset_set(pollent)) != NULL) {
136
+ transport->vtable->set_pollset_set(exec_ctx, transport, stream,
137
+ pollset_set);
138
+ } else {
139
+ abort();
140
+ }
132
141
  }
133
142
 
134
143
  void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
@@ -143,11 +152,14 @@ char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
143
152
  return transport->vtable->get_peer(exec_ctx, transport);
144
153
  }
145
154
 
146
- void grpc_transport_stream_op_finish_with_failure(
147
- grpc_exec_ctx *exec_ctx, grpc_transport_stream_op *op) {
148
- grpc_exec_ctx_enqueue(exec_ctx, op->recv_message_ready, false, NULL);
149
- grpc_exec_ctx_enqueue(exec_ctx, op->recv_initial_metadata_ready, false, NULL);
150
- grpc_exec_ctx_enqueue(exec_ctx, op->on_complete, false, NULL);
155
+ void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
156
+ grpc_transport_stream_op *op,
157
+ grpc_error *error) {
158
+ grpc_exec_ctx_sched(exec_ctx, op->recv_message_ready, GRPC_ERROR_REF(error),
159
+ NULL);
160
+ grpc_exec_ctx_sched(exec_ctx, op->recv_initial_metadata_ready,
161
+ GRPC_ERROR_REF(error), NULL);
162
+ grpc_exec_ctx_sched(exec_ctx, op->on_complete, error, NULL);
151
163
  }
152
164
 
153
165
  void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
@@ -171,11 +183,11 @@ typedef struct {
171
183
  grpc_closure closure;
172
184
  } close_message_data;
173
185
 
174
- static void free_message(grpc_exec_ctx *exec_ctx, void *p, bool iomgr_success) {
186
+ static void free_message(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) {
175
187
  close_message_data *cmd = p;
176
188
  gpr_slice_unref(cmd->message);
177
189
  if (cmd->then_call != NULL) {
178
- cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, iomgr_success);
190
+ cmd->then_call->cb(exec_ctx, cmd->then_call->cb_arg, GRPC_ERROR_REF(error));
179
191
  }
180
192
  gpr_free(cmd);
181
193
  }
@@ -37,6 +37,7 @@
37
37
  #include <stddef.h>
38
38
 
39
39
  #include "src/core/lib/channel/context.h"
40
+ #include "src/core/lib/iomgr/polling_entity.h"
40
41
  #include "src/core/lib/iomgr/pollset.h"
41
42
  #include "src/core/lib/iomgr/pollset_set.h"
42
43
  #include "src/core/lib/transport/byte_stream.h"
@@ -154,7 +155,7 @@ typedef struct grpc_transport_op {
154
155
  grpc_closure *on_connectivity_state_change;
155
156
  grpc_connectivity_state *connectivity_state;
156
157
  /** should the transport be disconnected */
157
- int disconnect;
158
+ grpc_error *disconnect_with_error;
158
159
  /** should we send a goaway?
159
160
  after a goaway is sent, once there are no more active calls on
160
161
  the transport, the transport should disconnect */
@@ -197,9 +198,8 @@ int grpc_transport_init_stream(grpc_exec_ctx *exec_ctx,
197
198
  grpc_stream_refcount *refcount,
198
199
  const void *server_data);
199
200
 
200
- void grpc_transport_set_pollset(grpc_exec_ctx *exec_ctx,
201
- grpc_transport *transport, grpc_stream *stream,
202
- grpc_pollset *pollset);
201
+ void grpc_transport_set_pops(grpc_exec_ctx *exec_ctx, grpc_transport *transport,
202
+ grpc_stream *stream, grpc_polling_entity *pollent);
203
203
 
204
204
  /* Destroy transport data for a stream.
205
205
 
@@ -216,7 +216,8 @@ void grpc_transport_destroy_stream(grpc_exec_ctx *exec_ctx,
216
216
  grpc_stream *stream, void *and_free_memory);
217
217
 
218
218
  void grpc_transport_stream_op_finish_with_failure(grpc_exec_ctx *exec_ctx,
219
- grpc_transport_stream_op *op);
219
+ grpc_transport_stream_op *op,
220
+ grpc_error *error);
220
221
 
221
222
  void grpc_transport_stream_op_add_cancellation(grpc_transport_stream_op *op,
222
223
  grpc_status_code status);
@@ -53,6 +53,10 @@ typedef struct grpc_transport_vtable {
53
53
  void (*set_pollset)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
54
54
  grpc_stream *stream, grpc_pollset *pollset);
55
55
 
56
+ /* implementation of grpc_transport_set_pollset */
57
+ void (*set_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
58
+ grpc_stream *stream, grpc_pollset_set *pollset_set);
59
+
56
60
  /* implementation of grpc_transport_perform_stream_op */
57
61
  void (*perform_stream_op)(grpc_exec_ctx *exec_ctx, grpc_transport *self,
58
62
  grpc_stream *stream, grpc_transport_stream_op *op);
@@ -63,8 +63,8 @@ static void put_metadata_list(gpr_strvec *b, grpc_metadata_batch md) {
63
63
  }
64
64
  if (gpr_time_cmp(md.deadline, gpr_inf_future(md.deadline.clock_type)) != 0) {
65
65
  char *tmp;
66
- gpr_asprintf(&tmp, " deadline=%lld.%09d", (long long)md.deadline.tv_sec,
67
- (int)md.deadline.tv_nsec);
66
+ gpr_asprintf(&tmp, " deadline=%"PRId64".%09d", md.deadline.tv_sec,
67
+ md.deadline.tv_nsec);
68
68
  gpr_strvec_add(b, tmp);
69
69
  }
70
70
  }
@@ -45,6 +45,8 @@ extern void grpc_resolver_dns_native_init(void);
45
45
  extern void grpc_resolver_dns_native_shutdown(void);
46
46
  extern void grpc_resolver_sockaddr_init(void);
47
47
  extern void grpc_resolver_sockaddr_shutdown(void);
48
+ extern void grpc_load_reporting_plugin_init(void);
49
+ extern void grpc_load_reporting_plugin_shutdown(void);
48
50
  extern void census_grpc_plugin_init(void);
49
51
  extern void census_grpc_plugin_shutdown(void);
50
52
 
@@ -61,6 +63,8 @@ void grpc_register_built_in_plugins(void) {
61
63
  grpc_resolver_dns_native_shutdown);
62
64
  grpc_register_plugin(grpc_resolver_sockaddr_init,
63
65
  grpc_resolver_sockaddr_shutdown);
66
+ grpc_register_plugin(grpc_load_reporting_plugin_init,
67
+ grpc_load_reporting_plugin_shutdown);
64
68
  grpc_register_plugin(census_grpc_plugin_init,
65
69
  census_grpc_plugin_shutdown);
66
70
  }
@@ -1,13 +1,41 @@
1
1
  # Generated by the protocol buffer compiler. DO NOT EDIT!
2
2
  # Source: math.proto for package 'math'
3
+ # Original file comments:
4
+ # Copyright 2015, Google Inc.
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are
9
+ # met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright
12
+ # notice, this list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above
14
+ # copyright notice, this list of conditions and the following disclaimer
15
+ # in the documentation and/or other materials provided with the
16
+ # distribution.
17
+ # * Neither the name of Google Inc. nor the names of its
18
+ # contributors may be used to endorse or promote products derived from
19
+ # this software without specific prior written permission.
20
+ #
21
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
3
33
 
4
34
  require 'grpc'
5
35
  require 'math'
6
36
 
7
37
  module Math
8
38
  module Math
9
-
10
- # TODO: add proto service documentation here
11
39
  class Service
12
40
 
13
41
  include GRPC::GenericService
@@ -16,9 +44,20 @@ module Math
16
44
  self.unmarshal_class_method = :decode
17
45
  self.service_name = 'math.Math'
18
46
 
47
+ # Div divides args.dividend by args.divisor and returns the quotient and
48
+ # remainder.
19
49
  rpc :Div, DivArgs, DivReply
50
+ # DivMany accepts an arbitrary number of division args from the client stream
51
+ # and sends back the results in the reply stream. The stream continues until
52
+ # the client closes its end; the server does the same after sending all the
53
+ # replies. The stream ends immediately if either end aborts.
20
54
  rpc :DivMany, stream(DivArgs), stream(DivReply)
55
+ # Fib generates numbers in the Fibonacci sequence. If args.limit > 0, Fib
56
+ # generates up to limit numbers; otherwise it continues until the call is
57
+ # canceled. Unlike Fib above, Fib has no final FibReply.
21
58
  rpc :Fib, FibArgs, stream(Num)
59
+ # Sum sums a stream of numbers, returning the final result once the stream
60
+ # is closed.
22
61
  rpc :Sum, stream(Num), Num
23
62
  end
24
63
 
@@ -101,30 +101,14 @@ static VALUE sym_message;
101
101
  static VALUE sym_status;
102
102
  static VALUE sym_cancelled;
103
103
 
104
- /* hash_all_calls is a hash of Call address -> reference count that is used to
105
- * track the creation and destruction of rb_call instances.
106
- */
107
- static VALUE hash_all_calls;
108
-
109
104
  /* Destroys a Call. */
110
105
  static void grpc_rb_call_destroy(void *p) {
111
- grpc_call *call = NULL;
112
- VALUE ref_count = Qnil;
106
+ grpc_call* call = NULL;
113
107
  if (p == NULL) {
114
108
  return;
115
- };
116
- call = (grpc_call *)p;
117
-
118
- ref_count = rb_hash_aref(hash_all_calls, OFFT2NUM((VALUE)call));
119
- if (ref_count == Qnil) {
120
- return; /* No longer in the hash, so already deleted */
121
- } else if (NUM2UINT(ref_count) == 1) {
122
- rb_hash_delete(hash_all_calls, OFFT2NUM((VALUE)call));
123
- grpc_call_destroy(call);
124
- } else {
125
- rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)call),
126
- UINT2NUM(NUM2UINT(ref_count) - 1));
127
109
  }
110
+ call = (grpc_call *)p;
111
+ grpc_call_destroy(call);
128
112
  }
129
113
 
130
114
  static size_t md_ary_datasize(const void *p) {
@@ -151,7 +135,7 @@ static const rb_data_type_t grpc_rb_md_ary_data_type = {
151
135
  * touches a hash object.
152
136
  * TODO(yugui) Directly use st_table and call the free function earlier?
153
137
  */
154
- 0,
138
+ 0,
155
139
  #endif
156
140
  };
157
141
 
@@ -163,12 +147,7 @@ static const rb_data_type_t grpc_call_data_type = {
163
147
  NULL,
164
148
  NULL,
165
149
  #ifdef RUBY_TYPED_FREE_IMMEDIATELY
166
- /* it is unsafe to specify RUBY_TYPED_FREE_IMMEDIATELY because
167
- * grpc_rb_call_destroy
168
- * touches a hash object.
169
- * TODO(yugui) Directly use st_table and call the free function earlier?
170
- */
171
- 0,
150
+ RUBY_TYPED_FREE_IMMEDIATELY
172
151
  #endif
173
152
  };
174
153
 
@@ -190,6 +169,11 @@ const char *grpc_call_error_detail_of(grpc_call_error err) {
190
169
  static VALUE grpc_rb_call_cancel(VALUE self) {
191
170
  grpc_call *call = NULL;
192
171
  grpc_call_error err;
172
+ if (RTYPEDDATA_DATA(self) == NULL) {
173
+ //This call has been closed
174
+ return Qnil;
175
+ }
176
+
193
177
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
194
178
  err = grpc_call_cancel(call, NULL);
195
179
  if (err != GRPC_CALL_OK) {
@@ -200,11 +184,29 @@ static VALUE grpc_rb_call_cancel(VALUE self) {
200
184
  return Qnil;
201
185
  }
202
186
 
187
+ /* Releases the c-level resources associated with a call
188
+ Once a call has been closed, no further requests can be
189
+ processed.
190
+ */
191
+ static VALUE grpc_rb_call_close(VALUE self) {
192
+ grpc_call *call = NULL;
193
+ TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
194
+ if(call != NULL) {
195
+ grpc_call_destroy(call);
196
+ RTYPEDDATA_DATA(self) = NULL;
197
+ }
198
+ return Qnil;
199
+ }
200
+
203
201
  /* Called to obtain the peer that this call is connected to. */
204
202
  static VALUE grpc_rb_call_get_peer(VALUE self) {
205
203
  VALUE res = Qnil;
206
204
  grpc_call *call = NULL;
207
205
  char *peer = NULL;
206
+ if (RTYPEDDATA_DATA(self) == NULL) {
207
+ rb_raise(grpc_rb_eCallError, "Cannot get peer value on closed call");
208
+ return Qnil;
209
+ }
208
210
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
209
211
  peer = grpc_call_get_peer(call);
210
212
  res = rb_str_new2(peer);
@@ -218,6 +220,10 @@ static VALUE grpc_rb_call_get_peer_cert(VALUE self) {
218
220
  grpc_call *call = NULL;
219
221
  VALUE res = Qnil;
220
222
  grpc_auth_context *ctx = NULL;
223
+ if (RTYPEDDATA_DATA(self) == NULL) {
224
+ rb_raise(grpc_rb_eCallError, "Cannot get peer cert on closed call");
225
+ return Qnil;
226
+ }
221
227
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
222
228
 
223
229
  ctx = grpc_call_auth_context(call);
@@ -323,6 +329,10 @@ static VALUE grpc_rb_call_set_credentials(VALUE self, VALUE credentials) {
323
329
  grpc_call *call = NULL;
324
330
  grpc_call_credentials *creds;
325
331
  grpc_call_error err;
332
+ if (RTYPEDDATA_DATA(self) == NULL) {
333
+ rb_raise(grpc_rb_eCallError, "Cannot set credentials of closed call");
334
+ return Qnil;
335
+ }
326
336
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
327
337
  creds = grpc_rb_get_wrapped_call_credentials(credentials);
328
338
  err = grpc_call_set_credentials(call, creds);
@@ -731,7 +741,7 @@ static VALUE grpc_run_batch_stack_build_result(run_batch_stack *st) {
731
741
  }
732
742
  tag = Object.new
733
743
  timeout = 10
734
- call.start_batch(cqueue, tag, timeout, ops)
744
+ call.start_batch(cq, tag, timeout, ops)
735
745
 
736
746
  Start a batch of operations defined in the array ops; when complete, post a
737
747
  completion of type 'tag' to the completion queue bound to the call.
@@ -749,6 +759,10 @@ static VALUE grpc_rb_call_run_batch(VALUE self, VALUE cqueue, VALUE tag,
749
759
  VALUE result = Qnil;
750
760
  VALUE rb_write_flag = rb_ivar_get(self, id_write_flag);
751
761
  unsigned write_flag = 0;
762
+ if (RTYPEDDATA_DATA(self) == NULL) {
763
+ rb_raise(grpc_rb_eCallError, "Cannot run batch on closed call");
764
+ return Qnil;
765
+ }
752
766
  TypedData_Get_Struct(self, grpc_call, &grpc_call_data_type, call);
753
767
 
754
768
  /* Validate the ops args, adding them to a ruby array */
@@ -888,6 +902,7 @@ void Init_grpc_call() {
888
902
  /* Add ruby analogues of the Call methods. */
889
903
  rb_define_method(grpc_rb_cCall, "run_batch", grpc_rb_call_run_batch, 4);
890
904
  rb_define_method(grpc_rb_cCall, "cancel", grpc_rb_call_cancel, 0);
905
+ rb_define_method(grpc_rb_cCall, "close", grpc_rb_call_close, 0);
891
906
  rb_define_method(grpc_rb_cCall, "peer", grpc_rb_call_get_peer, 0);
892
907
  rb_define_method(grpc_rb_cCall, "peer_cert", grpc_rb_call_get_peer_cert, 0);
893
908
  rb_define_method(grpc_rb_cCall, "status", grpc_rb_call_get_status, 0);
@@ -925,11 +940,6 @@ void Init_grpc_call() {
925
940
  "BatchResult", "send_message", "send_metadata", "send_close",
926
941
  "send_status", "message", "metadata", "status", "cancelled", NULL);
927
942
 
928
- /* The hash for reference counting calls, to ensure they can't be destroyed
929
- * more than once */
930
- hash_all_calls = rb_hash_new();
931
- rb_define_const(grpc_rb_cCall, "INTERNAL_ALL_CALLs", hash_all_calls);
932
-
933
943
  Init_grpc_error_codes();
934
944
  Init_grpc_op_codes();
935
945
  Init_grpc_write_flags();
@@ -944,16 +954,8 @@ grpc_call *grpc_rb_get_wrapped_call(VALUE v) {
944
954
 
945
955
  /* Obtains the wrapped object for a given call */
946
956
  VALUE grpc_rb_wrap_call(grpc_call *c) {
947
- VALUE obj = Qnil;
948
957
  if (c == NULL) {
949
958
  return Qnil;
950
959
  }
951
- obj = rb_hash_aref(hash_all_calls, OFFT2NUM((VALUE)c));
952
- if (obj == Qnil) { /* Not in the hash add it */
953
- rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)c), UINT2NUM(1));
954
- } else {
955
- rb_hash_aset(hash_all_calls, OFFT2NUM((VALUE)c),
956
- UINT2NUM(NUM2UINT(obj) + 1));
957
- }
958
960
  return TypedData_Wrap_Struct(grpc_rb_cCall, &grpc_call_data_type, c);
959
961
  }
@@ -373,7 +373,7 @@ static void Init_grpc_connectivity_states() {
373
373
  rb_define_const(grpc_rb_mConnectivityStates, "TRANSIENT_FAILURE",
374
374
  LONG2NUM(GRPC_CHANNEL_TRANSIENT_FAILURE));
375
375
  rb_define_const(grpc_rb_mConnectivityStates, "FATAL_FAILURE",
376
- LONG2NUM(GRPC_CHANNEL_FATAL_FAILURE));
376
+ LONG2NUM(GRPC_CHANNEL_SHUTDOWN));
377
377
  }
378
378
 
379
379
  void Init_grpc_channel() {
@@ -52,21 +52,41 @@ typedef struct next_call_stack {
52
52
  grpc_event event;
53
53
  gpr_timespec timeout;
54
54
  void *tag;
55
+ volatile int interrupted;
55
56
  } next_call_stack;
56
57
 
57
58
  /* Calls grpc_completion_queue_next without holding the ruby GIL */
58
59
  static void *grpc_rb_completion_queue_next_no_gil(void *param) {
59
60
  next_call_stack *const next_call = (next_call_stack*)param;
60
- next_call->event =
61
- grpc_completion_queue_next(next_call->cq, next_call->timeout, NULL);
61
+ gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN);
62
+ gpr_timespec deadline;
63
+ do {
64
+ deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment);
65
+ next_call->event = grpc_completion_queue_next(next_call->cq,
66
+ deadline, NULL);
67
+ if (next_call->event.type != GRPC_QUEUE_TIMEOUT ||
68
+ gpr_time_cmp(deadline, next_call->timeout) > 0) {
69
+ break;
70
+ }
71
+ } while (!next_call->interrupted);
62
72
  return NULL;
63
73
  }
64
74
 
65
75
  /* Calls grpc_completion_queue_pluck without holding the ruby GIL */
66
76
  static void *grpc_rb_completion_queue_pluck_no_gil(void *param) {
67
77
  next_call_stack *const next_call = (next_call_stack*)param;
68
- next_call->event = grpc_completion_queue_pluck(next_call->cq, next_call->tag,
69
- next_call->timeout, NULL);
78
+ gpr_timespec increment = gpr_time_from_millis(20, GPR_TIMESPAN);
79
+ gpr_timespec deadline;
80
+ do {
81
+ deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), increment);
82
+ next_call->event = grpc_completion_queue_pluck(next_call->cq,
83
+ next_call->tag,
84
+ deadline, NULL);
85
+ if (next_call->event.type != GRPC_QUEUE_TIMEOUT ||
86
+ gpr_time_cmp(deadline, next_call->timeout) > 0) {
87
+ break;
88
+ }
89
+ } while (!next_call->interrupted);
70
90
  return NULL;
71
91
  }
72
92
 
@@ -130,6 +150,14 @@ static rb_data_type_t grpc_rb_completion_queue_data_type = {
130
150
  #endif
131
151
  };
132
152
 
153
+ /* Releases the c-level resources associated with a completion queue */
154
+ static VALUE grpc_rb_completion_queue_close(VALUE self) {
155
+ grpc_completion_queue* cq = grpc_rb_get_wrapped_completion_queue(self);
156
+ grpc_rb_completion_queue_destroy(cq);
157
+ RTYPEDDATA_DATA(self) = NULL;
158
+ return Qnil;
159
+ }
160
+
133
161
  /* Allocates a completion queue. */
134
162
  static VALUE grpc_rb_completion_queue_alloc(VALUE cls) {
135
163
  grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
@@ -139,6 +167,11 @@ static VALUE grpc_rb_completion_queue_alloc(VALUE cls) {
139
167
  return TypedData_Wrap_Struct(cls, &grpc_rb_completion_queue_data_type, cq);
140
168
  }
141
169
 
170
+ static void unblock_func(void *param) {
171
+ next_call_stack *const next_call = (next_call_stack*)param;
172
+ next_call->interrupted = 1;
173
+ }
174
+
142
175
  /* Blocks until the next event for given tag is available, and returns the
143
176
  * event. */
144
177
  grpc_event grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
@@ -158,8 +191,23 @@ grpc_event grpc_rb_completion_queue_pluck_event(VALUE self, VALUE tag,
158
191
  next_call.tag = ROBJECT(tag);
159
192
  }
160
193
  next_call.event.type = GRPC_QUEUE_TIMEOUT;
161
- rb_thread_call_without_gvl(grpc_rb_completion_queue_pluck_no_gil,
162
- (void *)&next_call, NULL, NULL);
194
+ /* Loop until we finish a pluck without an interruption. The internal
195
+ pluck function runs either until it is interrupted or it gets an
196
+ event, or time runs out.
197
+
198
+ The basic reason we need this relatively complicated construction is that
199
+ we need to re-acquire the GVL when an interrupt comes in, so that the ruby
200
+ interpreter can do what it needs to do with the interrupt. But we also need
201
+ to get back to plucking when the interrupt has been handled. */
202
+ do {
203
+ next_call.interrupted = 0;
204
+ rb_thread_call_without_gvl(grpc_rb_completion_queue_pluck_no_gil,
205
+ (void *)&next_call, unblock_func,
206
+ (void *)&next_call);
207
+ /* If an interrupt prevented pluck from returning useful information, then
208
+ any plucks that did complete must have timed out */
209
+ } while (next_call.interrupted &&
210
+ next_call.event.type == GRPC_QUEUE_TIMEOUT);
163
211
  return next_call.event;
164
212
  }
165
213
 
@@ -172,6 +220,11 @@ void Init_grpc_completion_queue() {
172
220
  this func, so no separate initialization step is necessary. */
173
221
  rb_define_alloc_func(grpc_rb_cCompletionQueue,
174
222
  grpc_rb_completion_queue_alloc);
223
+
224
+ /* close: Provides a way to close the underlying file descriptor without
225
+ waiting for ruby garbage collection. */
226
+ rb_define_method(grpc_rb_cCompletionQueue, "close",
227
+ grpc_rb_completion_queue_close, 0);
175
228
  }
176
229
 
177
230
  /* Gets the wrapped completion queue from the ruby wrapper */