Browse files

Release the GIL on connect, bind, send + explicit client and engine t…

…eardown
  • Loading branch information...
1 parent 0b6ccbe commit f7aabd6f0a0b8adb07209e37b8226d03b20d6019 @methodmissing committed Jan 24, 2012
Showing with 105 additions and 7 deletions.
  1. +0 −1 README.rdoc
  2. +59 −4 ext/relp/client.c
  3. +18 −0 ext/relp/client.h
  4. +6 −1 ext/relp/engine.c
  5. +16 −1 ext/relp/server.c
  6. +6 −0 ext/relp/server.h
View
1 README.rdoc
@@ -106,7 +106,6 @@ Running tests
* Do not allow further method calls on lower level destroy calls on Relp::Client or Relp::Server instances
* Sanity check on_receive cb arity + test cases for error conditions in command callbacks
* Fix Rubinius and JRuby compile
-* rb_thread_blocking_region on connect, bind, send + explicit engine destroy
* engine destruct on handler error or error handler callback API ?
* Respect that Relp::Server could bind to multiple ports
* examples
View
63 ext/relp/client.c
@@ -81,6 +81,17 @@ static VALUE rb_relp_client_s_new(VALUE klass, VALUE engine_obj)
}
/*
+ * :nodoc:
+ * Destroys a client while the GIL is released.
+ *
+*/
+static VALUE rb_relp_nogvl_client_destroy(void *ptr)
+{
+ struct nogvl_client_destroy_args *args = ptr;
+ return (VALUE)relpEngineCltDestruct(args->engine, &args->client);
+}
+
+/*
* call-seq:
* client.destroy => nil
*
@@ -95,14 +106,38 @@ static VALUE rb_relp_client_s_new(VALUE klass, VALUE engine_obj)
static VALUE rb_relp_client_destroy(VALUE obj)
{
relpRetVal ret;
+ struct nogvl_client_destroy_args args;
RelpGetClient(obj);
- ret = relpEngineCltDestruct(client->engine, &client->client);
+ args.engine = client->engine;
+ args.client = client->client;
+ ret = (relpRetVal)rb_thread_blocking_region(rb_relp_nogvl_client_destroy, (void *)&args, RUBY_UBF_IO, 0);
RelpAssert(ret);
client->flags |= RELP_CLIENT_DESTROYED;
return Qnil;
}
/*
+ * :nodoc:
+ * Reconnects to a Relp server while the GIL is released.
+ *
+*/
+static VALUE rb_relp_nogvl_client_reconnect(void *ptr)
+{
+ return (VALUE)relpCltReconnect((relpClt_t *)ptr);
+}
+
+/*
+ * :nodoc:
+ * Connects to a Relp server while the GIL is released.
+ *
+*/
+static VALUE rb_relp_nogvl_client_connect(void *ptr)
+{
+ struct nogvl_client_connect_args *args = ptr;
+ return (VALUE)relpCltConnect(args->client, args->prot_family, args->port, args->host);
+}
+
+/*
* call-seq:
* client.connect(Socket::AF_INET, 'localhost', 518) => true
*
@@ -117,16 +152,21 @@ static VALUE rb_relp_client_destroy(VALUE obj)
static VALUE rb_relp_client_connect(VALUE obj, VALUE prot_family, VALUE host, VALUE port)
{
relpRetVal ret;
+ struct nogvl_client_connect_args args;
RelpGetClient(obj);
port = rb_obj_as_string(port);
Check_Type(host, T_STRING);
Check_Type(port, T_STRING);
Check_Type(prot_family, T_FIXNUM);
if (client->flags & RELP_CLIENT_INITIAL_CONNECT) {
- ret = relpCltConnect(client->client, NUM2INT(prot_family), (unsigned char*)StringValueCStr(port), (unsigned char*)StringValueCStr(host));
+ args.client = client->client;
+ args.prot_family = NUM2INT(prot_family);
+ args.host = (unsigned char*)StringValueCStr(host);
+ args.port = (unsigned char*)StringValueCStr(port);
+ ret = (relpRetVal)rb_thread_blocking_region(rb_relp_nogvl_client_connect, (void *)&args, RUBY_UBF_IO, 0);
if (ret == RELP_RET_OK) client->flags &= ~RELP_CLIENT_INITIAL_CONNECT;
} else {
- ret = relpCltReconnect(client->client);
+ ret = (relpRetVal)rb_thread_blocking_region(rb_relp_nogvl_client_reconnect, (void *)client->client, RUBY_UBF_IO, 0);
}
if(ret == RELP_RET_OK) {
@@ -139,6 +179,17 @@ static VALUE rb_relp_client_connect(VALUE obj, VALUE prot_family, VALUE host, VA
}
/*
+ * :nodoc:
+ * Sends a message to a Relp server while the GIL is released.
+ *
+*/
+static VALUE rb_relp_nogvl_client_send(void *ptr)
+{
+ struct nogvl_client_send_args *args = ptr;
+ return (VALUE)relpCltSendSyslog(args->client, args->msg, args->len);
+}
+
+/*
* call-seq:
* client.send("message") => true
*
@@ -154,9 +205,13 @@ static VALUE rb_relp_client_connect(VALUE obj, VALUE prot_family, VALUE host, VA
static VALUE rb_relp_client_send(VALUE obj, VALUE message)
{
relpRetVal ret;
+ struct nogvl_client_send_args args;
RelpGetClient(obj);
Check_Type(message, T_STRING);
- ret = relpCltSendSyslog(client->client, (unsigned char*)StringValueCStr(message), RSTRING_LEN(message) + 1);
+ args.client = client->client;
+ args.msg = (unsigned char*)StringValueCStr(message);
+ args.len = RSTRING_LEN(message) + 1;
+ ret = (relpRetVal)rb_thread_blocking_region(rb_relp_nogvl_client_send, (void *)&args, RUBY_UBF_IO, 0);
RelpAssert(ret);
return Qtrue;
}
View
18 ext/relp/client.h
@@ -54,6 +54,24 @@ typedef struct {
Data_Get_Struct(obj, relp_client_wrapper, client); \
if (!client) rb_raise(rb_eTypeError, "uninitialized RELP client!");
+struct nogvl_client_destroy_args {
+ relpEngine_t *engine;
+ relpClt_t *client;
+};
+
+struct nogvl_client_connect_args {
+ relpClt_t *client;
+ int prot_family;
+ unsigned char* host;
+ unsigned char* port;
+};
+
+struct nogvl_client_send_args {
+ relpClt_t *client;
+ unsigned char* msg;
+ int len;
+};
+
void _init_rb_relp_client();
#endif
View
7 ext/relp/engine.c
@@ -142,6 +142,11 @@ static VALUE rb_relp_engine_run(VALUE obj)
return INT2NUM(ret);
}
+static VALUE rb_relp_nogvl_engine_destroy(void *ptr)
+{
+ return (VALUE)relpEngineDestruct((relpEngine_t *)&ptr);
+}
+
/*
* call-seq:
* engine.destroy => nil
@@ -161,7 +166,7 @@ static VALUE rb_relp_engine_destroy(VALUE obj)
{
relpRetVal ret;
RelpGetEngine(obj);
- ret = relpEngineDestruct(&engine->engine);
+ ret = (relpRetVal)rb_thread_blocking_region(rb_relp_nogvl_engine_destroy, (void *)engine->engine, RUBY_UBF_IO, 0);
RelpAssert(ret);
engine->flags |= RELP_ENGINE_DESTROYED;
rb_relp_engine_flag_clients(engine);
View
17 ext/relp/server.c
@@ -149,6 +149,17 @@ static VALUE rb_relp_server_destroy(VALUE obj)
}
/*
+ * :nodoc:
+ * Binds a listner to the Relp engine while the GIL is released.
+ *
+*/
+static VALUE rb_relp_nogvl_server_bind(void *ptr)
+{
+ struct nogvl_server_bind_args *args = ptr;
+ return (VALUE)relpEngineAddListner2(args->engine, args->port, args->obj);
+}
+
+/*
* call-seq:
* server.bind(518) => boolean
*
@@ -164,10 +175,14 @@ static VALUE rb_relp_server_destroy(VALUE obj)
static VALUE rb_relp_server_bind(VALUE obj, VALUE port)
{
relpRetVal ret;
+ struct nogvl_server_bind_args args;
RelpGetServer(obj);
port = rb_obj_as_string(port);
Check_Type(port, T_STRING);
- ret = relpEngineAddListner2(server->engine, (unsigned char*)StringValueCStr(port), (void *)obj);
+ args.engine = server->engine;
+ args.port = (unsigned char*)StringValueCStr(port);
+ args.obj = (void *)obj;
+ ret = (relpRetVal)rb_thread_blocking_region(rb_relp_nogvl_server_bind, (void *)&args, RUBY_UBF_IO, 0);
RelpAssert(ret);
server->flags |= RELP_SERVER_BOUND;
return Qtrue;
View
6 ext/relp/server.h
@@ -53,6 +53,12 @@ typedef struct {
Data_Get_Struct(obj, relp_server_wrapper, server); \
if (!server) rb_raise(rb_eTypeError, "uninitialized RELP server!");
+struct nogvl_server_bind_args {
+ relpEngine_t *engine;
+ unsigned char* port;
+ void *obj;
+};
+
void _init_rb_relp_server();
#endif

0 comments on commit f7aabd6

Please sign in to comment.