about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-01-31 17:05:48 -0800
committerEric Wong <normalperson@yhbt.net>2011-01-31 17:19:32 -0800
commit8a1fc65c88dee174940735bb46074c72ac47ce61 (patch)
treec9f3daabd6431fecbb302a9815c4e8d3e5006b09
parent6479b6d3934b8930910e0057f516aa019dd7a8c7 (diff)
downloadkgio-8a1fc65c88dee174940735bb46074c72ac47ce61.tar.gz
We know that all versions of MRI have a small RFile structure
that is allocated in the same object slots as other Ruby types
and also zeroed on allocation.

This optimization enables us to fall back to using ivars in
case MRI changes or if we're used on other Rubies.
-rw-r--r--ext/kgio/autopush.c21
-rw-r--r--ext/kgio/extconf.rb8
2 files changed, 27 insertions, 2 deletions
diff --git a/ext/kgio/autopush.c b/ext/kgio/autopush.c
index fa24055..cc83fdb 100644
--- a/ext/kgio/autopush.c
+++ b/ext/kgio/autopush.c
@@ -38,6 +38,26 @@ enum autopush_state {
         AUTOPUSH_STATE_ACCEPTOR = 3
 };
 
+#if defined(R_CAST) && \
+    defined(HAVE_TYPE_STRUCT_RFILE) && \
+    defined(HAVE_TYPE_STRUCT_ROBJECT) && \
+    ((SIZEOF_STRUCT_RFILE + SIZEOF_INT) <= (SIZEOF_STRUCT_ROBJECT))
+
+struct AutopushSocket {
+        struct RFile rfile;
+        enum autopush_state autopush_state;
+};
+
+static enum autopush_state state_get(VALUE io)
+{
+        return ((struct AutopushSocket *)(io))->autopush_state;
+}
+
+static void state_set(VALUE io, enum autopush_state state)
+{
+        ((struct AutopushSocket *)(io))->autopush_state = state;
+}
+#else
 static enum autopush_state state_get(VALUE io)
 {
         VALUE val;
@@ -53,6 +73,7 @@ static void state_set(VALUE io, enum autopush_state state)
 {
         rb_ivar_set(io, id_autopush_state, INT2NUM(state));
 }
+#endif /* IVAR fallback */
 
 static enum autopush_state detect_acceptor_state(VALUE io);
 static void push_pending_data(VALUE io);
diff --git a/ext/kgio/extconf.rb b/ext/kgio/extconf.rb
index dcc1418..e7220a4 100644
--- a/ext/kgio/extconf.rb
+++ b/ext/kgio/extconf.rb
@@ -3,8 +3,9 @@ $CPPFLAGS << ' -D_GNU_SOURCE'
 
 have_func('accept4', %w(sys/socket.h))
 if have_header('ruby/io.h')
-  have_struct_member("rb_io_t", "fd", "ruby/io.h")
-  have_struct_member("rb_io_t", "mode", "ruby/io.h")
+  rubyio = %w(ruby.h ruby/io.h)
+  have_struct_member("rb_io_t", "fd", rubyio)
+  have_struct_member("rb_io_t", "mode", rubyio)
 else
   rubyio = %w(ruby.h rubyio.h)
   rb_io_t = have_type("OpenFile", rubyio) ? "OpenFile" : "rb_io_t"
@@ -13,6 +14,9 @@ else
   have_struct_member(rb_io_t, "mode", rubyio)
   have_func('rb_fdopen')
 end
+have_type("struct RFile", rubyio) and check_sizeof("struct RFile", rubyio)
+have_type("struct RObject") and check_sizeof("struct RObject")
+check_sizeof("int")
 have_func('rb_io_ascii8bit_binmode')
 have_func('rb_thread_blocking_region')
 have_func('rb_str_set_len')