From: Masaki Fukushima Date: 2000-02-26T14:20:38+09:00 Subject: [ruby-talk:01587] Re: Ruby/GTK and the mainloop Yasushi Shoji wrote: > using gtk_timeout_add turns into busy wait and it consumes most of the > cpu time by itself. That was why we, or I should say Masaki > Fukushima, fukusima@goto.info.waseda.ac.jp, changed it to idle_add in > ruby-list:16691. Sorry for late response. I've been absent this week. Yes, I proposed to use rb_thread_wait_for(100ms). > the problem, ruby keeps scheduling at least 100ms once it gets, was > already known at the time. He, Masaki Fukushima, also suggested using > only one select but both Ruby and Gtk+ has a chance to wait on I/O, so > he said it's difficult, if not impossible, to do it with current Ruby > and Gtk+. I also made a patch to integrate two `select' functions (gtk's one and ruby's) by using g_main_set_poll_func() and rb_thread_select(). I attached the patch below. But current rb_thread_select() has busy wait problem with more than one thread. So the patch is not applied to current Ruby/Gtk. --- Masaki Fukushima --- 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 +#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);