about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2011-03-13 09:48:18 +0000
committerEric Wong <normalperson@yhbt.net>2011-03-13 09:48:18 +0000
commitbd8334f5f3e901a3d54d3421dffb0db8efa024a9 (patch)
treec2d565032697b29a6fe87e31d87f819dc8c5ef52
parentc55831a01dab548fdf9eccb7529396f6582c6637 (diff)
While local filesystems are usually very fast, we are
pessimistic and should prepare for worst-case scenarios.  This
can use rb_thread_io_blocking_region() under Ruby 1.9.3dev.
-rw-r--r--ext/clogger_ext/blocking_helpers.h58
-rw-r--r--ext/clogger_ext/clogger.c1
-rw-r--r--ext/clogger_ext/extconf.rb2
3 files changed, 61 insertions, 0 deletions
diff --git a/ext/clogger_ext/blocking_helpers.h b/ext/clogger_ext/blocking_helpers.h
new file mode 100644
index 0000000..dd46cea
--- /dev/null
+++ b/ext/clogger_ext/blocking_helpers.h
@@ -0,0 +1,58 @@
+#ifdef HAVE_RB_THREAD_BLOCKING_REGION
+struct stat_args { const char *path; struct stat *buf; };
+static VALUE ng_stat(void *ptr)
+{
+        struct stat_args *a = ptr;
+        return (VALUE)stat(a->path, a->buf);
+}
+static int my_stat(const char *path, struct stat *buf)
+{
+        struct stat_args a;
+
+        a.path = path;
+        a.buf = buf;
+        return (int)rb_thread_blocking_region(ng_stat, &a, RUBY_UBF_IO, 0);
+}
+#ifndef HAVE_RB_THREAD_IO_BLOCKING_REGION
+#  define rb_thread_io_blocking_region(fn,data,fd) \
+           rb_thread_blocking_region((fn),(data), RUBY_UBF_IO, 0)
+#endif
+
+struct fstat_args { int fd; struct stat *buf; };
+static VALUE ng_fstat(void *ptr)
+{
+        struct fstat_args *a = ptr;
+        return (VALUE)fstat(a->fd, a->buf);
+}
+
+static int my_fstat(int fd, struct stat *buf)
+{
+        struct fstat_args a;
+
+        a.fd = fd;
+        a.buf = buf;
+        return (int)rb_thread_io_blocking_region(ng_fstat, &a, fd);
+}
+
+struct write_args { int fd; const void *buf; size_t count; };
+static VALUE ng_write(void *ptr)
+{
+        struct write_args *a = ptr;
+        return (VALUE)write(a->fd, a->buf, a->count);
+}
+static ssize_t my_write(int fd, const void *buf, size_t count)
+{
+        struct write_args a;
+        ssize_t r;
+
+        a.fd = fd;
+        a.buf = buf;
+        a.count = count;
+        r = (ssize_t)rb_thread_io_blocking_region(ng_write, &a, fd);
+
+        return r;
+}
+#  define stat(fd,buf) my_stat((fd),(buf))
+#  define fstat(fd,buf) my_fstat((fd),(buf))
+#  define write(fd,buf,count) my_write((fd),(buf),(count))
+#endif
diff --git a/ext/clogger_ext/clogger.c b/ext/clogger_ext/clogger.c
index 1641f48..0adefa4 100644
--- a/ext/clogger_ext/clogger.c
+++ b/ext/clogger_ext/clogger.c
@@ -19,6 +19,7 @@
 #include <time.h>
 #include "ruby_1_9_compat.h"
 #include "broken_system_compat.h"
+#include "blocking_helpers.h"
 
 /*
  * Availability of a monotonic clock needs to be detected at runtime
diff --git a/ext/clogger_ext/extconf.rb b/ext/clogger_ext/extconf.rb
index 85f2d30..27f07d0 100644
--- a/ext/clogger_ext/extconf.rb
+++ b/ext/clogger_ext/extconf.rb
@@ -22,6 +22,8 @@ begin
   have_func('localtime_r', 'time.h') or raise "localtime_r needed"
   have_func('gmtime_r', 'time.h') or raise "gmtime_r needed"
   have_func('rb_str_set_len', 'ruby.h')
+  have_func('rb_thread_blocking_region', 'ruby.h')
+  have_func('rb_thread_io_blocking_region', 'ruby.h')
   dir_config('clogger_ext')
   create_makefile('clogger_ext')
 rescue Object => err