use rb_thread_call_without_gvl for Ruby 2+
[clogger.git] / ext / clogger_ext / blocking_helpers.h
blobc03c2f5b0a5cf9f254c91a0bcf65c13109c3821d
1 #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) && defined(HAVE_RUBY_THREAD_H)
2 /* Ruby 2.0+ */
3 # include <ruby/thread.h>
4 # define WITHOUT_GVL(fn,a,ubf,b) \
5 rb_thread_call_without_gvl((fn),(a),(ubf),(b))
6 #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
7 typedef VALUE (*my_blocking_fn_t)(void*);
8 # define WITHOUT_GVL(fn,a,ubf,b) \
9 rb_thread_blocking_region((my_blocking_fn_t)(fn),(a),(ubf),(b))
10 #endif
12 #ifdef WITHOUT_GVL
13 struct stat_args { int err; const char *path; struct stat *buf; };
14 static void * ng_stat(void *ptr)
16 struct stat_args *a = ptr;
17 a->err = stat(a->path, a->buf);
18 return NULL;
21 static int my_stat(const char *path, struct stat *buf)
23 struct stat_args a;
25 a.path = path;
26 a.buf = buf;
27 WITHOUT_GVL(ng_stat, &a, RUBY_UBF_IO, 0);
28 return a.err;
31 #ifndef HAVE_RB_THREAD_IO_BLOCKING_REGION
32 # define rb_thread_io_blocking_region(fn,data,fd) \
33 WITHOUT_GVL((fn),(data), RUBY_UBF_IO, 0)
34 #else
35 VALUE rb_thread_io_blocking_region(VALUE(*)(void *), void *, int);
36 #endif
38 struct write_args { int fd; const void *buf; size_t count; };
39 static VALUE ng_write(void *ptr)
41 struct write_args *a = ptr;
43 return (VALUE)write(a->fd, a->buf, a->count);
45 static ssize_t my_write(int fd, const void *buf, size_t count)
47 struct write_args a;
48 ssize_t r;
50 a.fd = fd;
51 a.buf = buf;
52 a.count = count;
53 r = (ssize_t)rb_thread_io_blocking_region(ng_write, &a, fd);
55 return r;
57 # define stat(path,buf) my_stat((path),(buf))
58 # define write(fd,buf,count) my_write((fd),(buf),(count))
59 #endif /* !WITHOUT_GVL */