On Wed, Feb 23, 2000 at 02:56:10AM -0500, Yasushi Shoji wrote:
> Hello Ian,
> 
> sorry for the late post.  I'm not the expert of Ruby, Gtk+, nor
> threads, but was interested in this topic.

Well, I thank you for responding.  I was thinking no one was interested ;)


> From: Ian Main <imain / gtk.org>
> Subject: [ruby-talk:01508] Ruby/GTK and the mainloop
> Date: Fri, 18 Feb 2000 23:19:56 -0800
> 
> > Now, this doesn't cause too huge of problems, but I did notice the
> > sluggish redraw gtk had when run from ruby (because it only gets control
> > to redraw every 100ms).  It also makes the applications consume a small
> > amount of CPU when idle.
> > 
> > If I were to embed ruby into entity, it would also cause IO handlers to be
> > called with a 100ms delay.  I realize this could be made into a smaller
> > amount (and indeed this is what I did with the Ruby/GTK to make it "feel"
> > faster), but this causes more idle CPU usage.. not a big deal on my machine,
> > but the actual amount will vary depending on the platform.
> 
> I thought 100ms was the best we could get.
> 
> the problem we had was that, as the source code shows,
> 
> #if 1
>     gtk_idle_add((GtkFunction)idle, 0);
> #else
>     /* use timeout to avoid busy wait */
>     gtk_timeout_add(100, (GtkFunction)idle, 0);
> #endif

Yes, what I did was change the idle () function:

static gint
idle()
{
    struct timeval wait;
    
    wait.tv_sec  = 0;
    wait.tv_usec = 1000; /* 100ms */
    
    CHECK_INTS;
    if (!rb_thread_critical) rb_thread_wait_for(wait);
  
    return Qtrue;
}

If I am correct, what ends up happening in rb_thread_wait_for (), is that it
calls thread_schedule with a timeout of (in this case) 100ms.  If there are
no other active threads, it sits in select for 100ms, and then returns to
give gtk a chance to run.  Changing the above to 10ms, means that gtk gets
control back faster (so long as no other ruby threads are running).
 
> 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.
> 
> 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+.

Yeah, it is impossible with the current ruby and gtk, because they both
expect to have control over the main loop.  What I would propose, is to
allow ruby to hook into other mainloops (essentially hook into their
select()).  Note that this applies not just to gtk, but any other
application or toolkit that expects main loop control.

GTK has good facilities for this.. from looking through ruby source code
again, it looks like ruby needs only:

* The ablity watch file descriptors for read/write readiness.
* A timeout for sleep() and similar functions.

What we can do is extrapolate that in the ruby core, so that when ruby needs
these facilities, it calls a specific function in ruby.  We then set it up
so that in the end these use function pointers, defaulting to the native
ruby versions.  A function in ruby could then allow us to override these
functions inside ruby, and in the case of the gtk bindings, they would
provide ruby-compatible wrappers around gdk_input_add (), and
gtk_timeout_add ().

This will then provide us with a single point of control (inside gtk), and
everyone would be happy.

The one thing to note on this, is that, in the case of gtk, the call to
setup the new select handlers in ruby would have to be called after you call
gtk_init(), but this should be fine.

Hopefully I am not missing any issues here.. if someone knows something I
don't please let me know! :)
 
> > So the point of all this, is that I'm wondering if you would be interested
> > in implementing a similar thing in Ruby ?  I would be willing to help in any
> > way possible, including an attempt at supplying patches if this is what it
> > will take.
> 
> I'd like to see if you already have a patch for this one.  I don't
> think there is any problem to include your patch if it works.

I don't have one yet.. I'm busy rewriting parts of entity.. once that's
done I'm going to embed ruby, and at that point I'll look into fixing this up.

> ps. is that why text widget seems slower on Ruby/Gtk than native Gtk+?

Yes, that's exactly why.  GTK is only getting a chance to refresh the screen
every 100ms, which is noticible when scrolling, or typing etc.

The other thing that might be nice is the ability to control the length of
the context switches at runtime..  dunno how plausable that is though...


Thanks,
	
	  Ian