You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by mc...@apache.org on 2014/12/08 15:02:57 UTC

qpid-proton git commit: PROTON-752: Release the GIL on blocking calls in Ruby.

Repository: qpid-proton
Updated Branches:
  refs/heads/master d549ec388 -> 1dc43c6c3


PROTON-752: Release the GIL on blocking calls in Ruby.

Added a wrapper call for pn_messenger_recv, pn_messenger_send and
pn_messenger_work that calls the appropriate method for the version
of Ruby to release the GIL until the call returns in C.

Added to both CMakeLists.txt for the Ruby bindings, and also to the
extconf.rb file for the gem, a macro named RUBY## (where ## is 18, 19,
20 or 21 depending on the version of Ruby) to ensure the right API is
compiled into the extension since the API is different between 1.9 and
2.x and non-existent in 1.8, where it's a no-op.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/1dc43c6c
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/1dc43c6c
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/1dc43c6c

Branch: refs/heads/master
Commit: 1dc43c6c30a9825961ee42b5249092ce3f9f4984
Parents: d549ec3
Author: Darryl L. Pierce <mc...@gmail.com>
Authored: Tue Dec 2 13:48:37 2014 -0500
Committer: Darryl L. Pierce <mc...@gmail.com>
Committed: Mon Dec 8 09:02:31 2014 -0500

----------------------------------------------------------------------
 proton-c/bindings/ruby/CMakeLists.txt         |   7 +
 proton-c/bindings/ruby/ext/cproton/extconf.rb |   4 +
 proton-c/bindings/ruby/ruby.i                 | 147 +++++++++++++++++++++
 3 files changed, 158 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1dc43c6c/proton-c/bindings/ruby/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/CMakeLists.txt b/proton-c/bindings/ruby/CMakeLists.txt
index e77e4de..ee7f955 100644
--- a/proton-c/bindings/ruby/CMakeLists.txt
+++ b/proton-c/bindings/ruby/CMakeLists.txt
@@ -23,9 +23,16 @@ endif (NOT DEFAULT_RUBY_TESTING)
 list(APPEND SWIG_MODULE_cproton-ruby_EXTRA_DEPS
     ${CMAKE_SOURCE_DIR}/proton-c/include/proton/cproton.i
 )
+
 include_directories (${RUBY_INCLUDE_PATH})
 swig_add_module(cproton-ruby ruby ruby.i)
 swig_link_libraries(cproton-ruby ${BINDING_DEPS} ${RUBY_LIBRARY})
+
+# set a compiler macro to relay the Ruby version to the extension
+STRING(REPLACE "." "" CFLAG_RUBY_VERSION "${RUBY_VERSION}")
+STRING(SUBSTRING "${CFLAG_RUBY_VERSION}" 0 2 CFLAG_RUBY_VERSION)
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DRUBY${CFLAG_RUBY_VERSION}")
+
 set_target_properties(cproton-ruby
     PROPERTIES
     PREFIX ""

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1dc43c6c/proton-c/bindings/ruby/ext/cproton/extconf.rb
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/ext/cproton/extconf.rb b/proton-c/bindings/ruby/ext/cproton/extconf.rb
index bca858e..52fbed8 100644
--- a/proton-c/bindings/ruby/ext/cproton/extconf.rb
+++ b/proton-c/bindings/ruby/ext/cproton/extconf.rb
@@ -19,6 +19,10 @@
 
 require 'mkmf'
 
+# set the ruby version compiler flag
+runtime_version = RUBY_VERSION.gsub(/\./,'')[0,2]
+$CFLAGS << " -DRUBY#{runtime_version}"
+
 dir_config("qpid-proton")
 
 REQUIRED_LIBRARIES = [

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/1dc43c6c/proton-c/bindings/ruby/ruby.i
----------------------------------------------------------------------
diff --git a/proton-c/bindings/ruby/ruby.i b/proton-c/bindings/ruby/ruby.i
index 1199875..888c64d 100644
--- a/proton-c/bindings/ruby/ruby.i
+++ b/proton-c/bindings/ruby/ruby.i
@@ -344,4 +344,151 @@ bool pn_ssl_get_cipher_name(pn_ssl_t *ssl, char *OUTPUT, size_t MAX_OUTPUT_SIZE)
 bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *OUTPUT, size_t MAX_OUTPUT_SIZE);
 %ignore pn_ssl_get_protocol_name;
 
+%inline %{
+#if defined(RUBY20) || defined(RUBY21)
+
+  typedef void *non_blocking_return_t;
+#define RB_BLOCKING_CALL rb_thread_call_without_gvl
+
+#elif defined(RUBY19)
+
+    typedef VALUE non_blocking_return_t;
+#define RB_BLOCKING_CALL rb_thread_blocking_region
+
+#endif
+  %}
+
+%rename(pn_messenger_send) wrap_pn_messenger_send;
+%rename(pn_messenger_recv) wrap_pn_messenger_recv;
+%rename(pn_messenger_work) wrap_pn_messenger_work;
+
+%inline %{
+
+#if defined(RB_BLOCKING_CALL)
+
+    static non_blocking_return_t pn_messenger_send_no_gvl(void *args) {
+    VALUE result = Qnil;
+    pn_messenger_t *messenger = (pn_messenger_t *)((void **)args)[0];
+    int *limit = (int *)((void **)args)[1];
+
+    int rc = pn_messenger_send(messenger, *limit);
+
+    result = INT2NUM(rc);
+    return (non_blocking_return_t )result;
+    }
+
+    static non_blocking_return_t pn_messenger_recv_no_gvl(void *args) {
+    VALUE result = Qnil;
+    pn_messenger_t *messenger = (pn_messenger_t *)((void **)args)[0];
+    int *limit = (int *)((void **)args)[1];
+
+    int rc = pn_messenger_recv(messenger, *limit);
+
+    result = INT2NUM(rc);
+    return (non_blocking_return_t )result;
+  }
+
+    static non_blocking_return_t pn_messenger_work_no_gvl(void *args) {
+      VALUE result = Qnil;
+      pn_messenger_t *messenger = (pn_messenger_t *)((void **)args)[0];
+      int *timeout = (int *)((void **)args)[1];
+
+      int rc = pn_messenger_work(messenger, *timeout);
+
+      result = INT2NUM(rc);
+      return (non_blocking_return_t )result;
+    }
+
+#endif
+
+  int wrap_pn_messenger_send(pn_messenger_t *messenger, int limit) {
+    int result = 0;
+
+#if defined(RB_BLOCKING_CALL)
+
+    // only release the gil if we're blocking
+    if(pn_messenger_is_blocking(messenger)) {
+      VALUE rc;
+      void* args[2];
+
+      args[0] = messenger;
+      args[1] = &limit;
+
+      rc = RB_BLOCKING_CALL(pn_messenger_send_no_gvl,
+                            &args, RUBY_UBF_PROCESS, NULL);
+
+      if(RTEST(rc))
+        {
+          result = FIX2INT(rc);
+        }
+    }
+
+#else // !defined(RB_BLOCKING_CALL)
+    result = pn_messenger_send(messenger, limit);
+#endif // defined(RB_BLOCKING_CALL)
+
+    return result;
+  }
+
+  int wrap_pn_messenger_recv(pn_messenger_t *messenger, int limit) {
+    int result = 0;
+
+#if defined(RB_BLOCKING_CALL)
+    // only release the gil if we're blocking
+    if(pn_messenger_is_blocking(messenger)) {
+      VALUE rc;
+      void* args[2];
+
+      args[0] = messenger;
+      args[1] = &limit;
+
+      rc = RB_BLOCKING_CALL(pn_messenger_recv_no_gvl,
+                            &args, RUBY_UBF_PROCESS, NULL);
+
+      if(RTEST(rc))
+        {
+          result = FIX2INT(rc);
+        }
+
+    } else {
+      result = pn_messenger_recv(messenger, limit);
+    }
+#else // !defined(RB_BLOCKING_CALL)
+    result = pn_messenger_recv(messenger, limit);
+#endif // defined(RB_BLOCKING_CALL)
+
+      return result;
+  }
+
+  int wrap_pn_messenger_work(pn_messenger_t *messenger, int timeout) {
+    int result = 0;
+
+#if defined(RB_BLOCKING_CALL)
+    // only release the gil if we're blocking
+    if(timeout) {
+      VALUE rc;
+      void* args[2];
+
+      args[0] = messenger;
+      args[1] = &timeout;
+
+      rc = RB_BLOCKING_CALL(pn_messenger_work_no_gvl,
+                            &args, RUBY_UBF_PROCESS, NULL);
+
+      if(RTEST(rc))
+        {
+          result = FIX2INT(rc);
+        }
+    } else {
+      result = pn_messenger_work(messenger, timeout);
+    }
+#else
+    result = pn_messenger_work(messenger, timeout);
+#endif
+
+    return result;
+  }
+
+  %}
+
 %include "proton/cproton.i"


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org