When Philippe and I worked on SystemTimer together we went back and forth about how much to write in Ruby and how much to write in C. Writing purely at the C level gave us more control over what was happening in the Ruby process as we installed and cleared signal handlers and such, but working in Ruby produced far more readable code.

Ultimately we ended up writing a hybrid—Ruby code that calls C code that calls back into Ruby code for a few interesting bits. When I go back and look at the result now, I’m pretty happy with it. There was one trick we had to pull in our situation, however, to ensure everything went according to plan. Since we entered C code to perform low level operations with timers we felt we didn’t want our code to be interrupted by Ruby’s thread scheduling. We wanted to ensure the timer got set up properly without the chance of another thread being scheduled. At first this led is to try to write as much in C as possible, since we wouldn’t ever hit the Ruby thread scheduler. Eventually we realized we could clean up a bunch of C code by extracting Ruby methods. To prevent other threads from being scheduled, we simply extracted C functions to wrap the Ruby methods, like this one.


  static void install_ruby_sigalrm_handler(VALUE self) {
    rb_thread_critical = 1;
    rb_funcall(self, rb_intern("install_ruby_sigalrm_handler"), 0);
    rb_thread_critical = 0;
  }

The C function install_ruby_sigalrm_handler is called by another C function, and is quite readable in that context. If you’re reading the C code, you don’t even have to know it’s calling back to Ruby. All the C function does, however, is set rb_thread_critical and then call back into Ruby code. rb_thread_critical is the equivalent of Thread.critical in the Ruby API. When it is set, Ruby will not schedule another thread (except in a few cases documented with Thread.critical). Using this simple tool we were able to effectively blend Ruby and C code without worrying about our operations being preempted. Arigatoo, Matsumoto-san.

Sorry, comments are closed for this article.