福嶋です。

Hiroshi Igarashi <igarashi / ueda.info.waseda.ac.jp> wrote:
> > と書きましたが、g_main_set_poll_func() というglibの関数を使えば
> > gtk側でI/Oのポーリングに使われる関数を差し替えられるようです。こ
> > れを使ってruby側で待っているfdとまとめてselect()するような関数を
> > 書けば全て解決できるのかも。
> 
> 確かにglibのリファレンスマニュアルを読むとまさに
> 
> This function could possibly be used to integrate
>  the GLib event loop with an external event loop.
> 
> なんて書いてあります。もしpolling関数を差し換えるなら

rb_thread_select()を使うものを書いてみました。
といっても、ほとんど gmain.c の g_poll() と同じです。
select()を置き換えただけ。

ただ、速度的には現在のSNAPSHOTのものとほとんど変らない感じです。
さらに、rb_thread_select()には問題があって、スレッドが複数ある状
態では busy wait になる可能性があります。

というわけで、現時点ではこの方法を採用するメリットはほとんど無い
ようです。将来 rb_thread_select() の実装が改善された時にために、
一応 #if 0 で囲ったパッチを付けておきます。SNAPSHOTへの差分です。


--- rbgtk.c.orig Sun Sep 12 22:34:29 1999 +++ rbgtk.c Mon Sep 13 22:33:53 1999 @@ -2209,6 +2209,69 @@ return Qtrue; } +#if 0 /* rb_thread_select() may cause busy wait */ + +#ifdef NATIVE_WIN32 +# error see gmain.c(g_poll) and implement WIN32 version of rbgtk_poll() +#else /* not NATIVE_WIN32 */ + +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif + +static gint +rbgtk_poll (GPollFD *fds, + guint nfds, + gint timeout) +{ + struct timeval tv; + fd_set rset, wset, xset; + GPollFD *f; + int ready; + int maxfd = 0; + + FD_ZERO (&rset); + FD_ZERO (&wset); + FD_ZERO (&xset); + + for (f = fds; f < &fds[nfds]; ++f) + if (f->fd >= 0) + { + if (f->events & G_IO_IN) + FD_SET (f->fd, &rset); + if (f->events & G_IO_OUT) + FD_SET (f->fd, &wset); + if (f->events & G_IO_PRI) + FD_SET (f->fd, &xset); + if (f->fd > maxfd && (f->events & (G_IO_IN|G_IO_OUT|G_IO_PRI))) + maxfd = f->fd; + } + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + ready = rb_thread_select (maxfd + 1, &rset, &wset, &xset, + timeout == -1 ? NULL : &tv); + if (ready > 0) + for (f = fds; f < &fds[nfds]; ++f) + { + f->revents = 0; + if (f->fd >= 0) + { + if (FD_ISSET (f->fd, &rset)) + f->revents |= G_IO_IN; + if (FD_ISSET (f->fd, &wset)) + f->revents |= G_IO_OUT; + if (FD_ISSET (f->fd, &xset)) + f->revents |= G_IO_PRI; + } + } + + return ready; +} +#endif /* not NATIVE_WIN32 */ + +#endif /* 0 */ + /* * Init */ @@ -2398,6 +2461,9 @@ #else /* use timeout to avoid busy wait */ gtk_timeout_add(100, (GtkFunction)idle, 0); +#endif +#if 0 + g_main_set_poll_func(rbgtk_poll); #endif rb_global_variable(&warn_handler);
--- 福嶋正機