RPM Community Forums

Mailing List Message of <rpm-cvs>

[CVS] RPM: rpm-5_3: rpm/ruby/ Makefile.am hello.rb xruby.c

From: Jeff Johnson <jbj@rpm5.org>
Date: Sun 19 Sep 2010 - 20:59:02 CEST
Message-Id: <20100919185902.5CF96C764D@rpm5.org>
  RPM Package Manager, CVS Repository
  /cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  jbj@rpm5.org
  Module: rpm                              Date:   19-Sep-2010 20:59:02
  Branch: rpm-5_3                          Handle: 2010091918590100

  Added files:              (Branch: rpm-5_3)
    rpm/ruby                hello.rb xruby.c
  Modified files:           (Branch: rpm-5_3)
    rpm/ruby                Makefile.am

  Log:
    - import a working ruby interpreter co-routine.

  Summary:
    Revision    Changes     Path
    1.6.2.1     +5  -3      rpm/ruby/Makefile.am
    1.1.2.1     +38 -0      rpm/ruby/hello.rb
    1.1.2.1     +260 -0     rpm/ruby/xruby.c
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/ruby/Makefile.am
  ============================================================================
  $ cvs diff -u -r1.6 -r1.6.2.1 Makefile.am
  --- rpm/ruby/Makefile.am	26 Dec 2009 16:23:44 -0000	1.6
  +++ rpm/ruby/Makefile.am	19 Sep 2010 18:59:01 -0000	1.6.2.1
  @@ -20,9 +20,8 @@
   	@WITH_XAR_CPPFLAGS@ \
   	@WITH_ZLIB_CPPFLAGS@
   
  -EXTRA_DIST = \
  -	tscripts
  -EXTRA_PROGRAMS =
  +EXTRA_DIST = tscripts hello.rb
  +EXTRA_PROGRAMS = xruby
   
   RPMMISC_LDADD_COMMON = \
   	$(top_builddir)/misc/librpmmisc.la \
  @@ -73,6 +72,9 @@
   trb_SOURCES = trb.c
   trb_LDADD = librpmrbm.la $(RPM_LDADD_COMMON)
   
  +xruby_SOURCES = xruby.c
  +xruby_LDADD = $(RPMIO_LDADD_COMMON)
  +
   .PHONY:	lint
   lint:
   	$(LINT) $(DEFS) $(INCLUDES) $(rpmrb_la_sources)
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/ruby/hello.rb
  ============================================================================
  $ cvs diff -u -r0 -r1.1.2.1 hello.rb
  --- /dev/null	2010-09-19 20:55:01.000000000 +0200
  +++ hello.rb	2010-09-19 20:59:02.272014565 +0200
  @@ -0,0 +1,38 @@
  +puts "~~~~> Hello World!  The time is #{Time.now}."
  +
  +puts "~~~~> Doing relay from #{__FILE__}:#{__LINE__}"
  +relay_from_ruby_to_main
  +puts "~~~~> OMG, back from main!! :-)"
  +
  +require 'date'
  +p Date.today
  +
  +require 'fileutils'
  +p FileUtils
  +include FileUtils::Verbose
  +touch 'foobar'
  +
  +def yasume
  +  Thread.pass if rand(2) == 1
  +end
  +
  +def recurse(n = 0)
  +  relay_from_ruby_to_main
  +  yasume
  +
  +  if n < 500
  +    print "#{Thread.current} recursing at #{n}...\n"
  +    yasume
  +
  +    recurse(n + 1)
  +    yasume
  +  end
  +end
  +
  +threads = 10.times.map do
  +  Thread.new { recurse }
  +end
  +
  +Thread.pass while threads.any? {|t| t.alive? }
  +
  +puts 'GOOD JOB! :-)'
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/ruby/xruby.c
  ============================================================================
  $ cvs diff -u -r0 -r1.1.2.1 xruby.c
  --- /dev/null	2010-09-19 20:55:01.000000000 +0200
  +++ xruby.c	2010-09-19 20:59:02.302018131 +0200
  @@ -0,0 +1,260 @@
  +/* stack size of the couroutine that will run Ruby */
  +#define DEMONSTRATION_STACK_SIZE (4*(1024*1024)) /* 4 MiB */
  +
  +#define	DEMONSTRATE_PTHREAD
  +#define	DEMONSTRATE_DYNAMIC
  +#define	HAVE_RUBY_SYSINIT
  +#define	HAVE_RUBY_BIND_STACK
  +#define HAVE_PTHREAD_ATTR_SETSTACK
  +
  +#define	true	1
  +#define false	0
  +typedef unsigned bool;
  +
  +#include <stdio.h>
  +#include <stdlib.h>
  +#include <stdbool.h>
  +#include <ruby.h>
  +
  +#ifdef DEMONSTRATE_PCL
  +#include <pcl.h>
  +static coroutine_t ruby_coroutine;
  +#endif
  +
  +#ifdef DEMONSTRATE_PTHREAD
  +#include <pthread.h>
  +static pthread_t ruby_coroutine;
  +static pthread_mutex_t main_coroutine_lock;
  +static pthread_mutex_t ruby_coroutine_lock;
  +#endif
  +
  +#ifdef DEMONSTRATE_UCONTEXT
  +#ifdef HAVE_SYS_UCONTEXT_H
  +#include <sys/ucontext.h>
  +#else
  +#include <ucontext.h>
  +#endif
  +static ucontext_t main_coroutine;
  +static ucontext_t ruby_coroutine;
  +#endif
  +
  +#ifdef DEMONSTRATE_STATIC
  +static size_t ruby_coroutine_stack_size;
  +static char ruby_coroutine_stack[DEMONSTRATION_STACK_SIZE];
  +#endif
  +
  +#ifdef DEMONSTRATE_DYNAMIC
  +static size_t ruby_coroutine_stack_size = DEMONSTRATION_STACK_SIZE;
  +static char* ruby_coroutine_stack;
  +#endif
  +
  +static bool ruby_coroutine_finished;
  +
  +/* puts the Ruby coroutine in control */
  +static void relay_from_main_to_ruby()
  +{
  +    printf("Relay: main => ruby\n");
  +
  +#ifdef DEMONSTRATE_PCL
  +    co_call(ruby_coroutine);
  +#endif
  +
  +#ifdef DEMONSTRATE_PTHREAD
  +    pthread_mutex_unlock(&ruby_coroutine_lock);
  +    pthread_mutex_lock(&main_coroutine_lock);
  +#endif
  +
  +#ifdef DEMONSTRATE_UCONTEXT
  +    swapcontext(&main_coroutine, &ruby_coroutine);
  +#endif
  +
  +    printf("Relay: main <= ruby\n");
  +}
  +
  +/* puts the main C program in control */
  +static VALUE relay_from_ruby_to_main(VALUE self)
  +{
  +    printf("Relay: ruby => main\n");
  +
  +#ifdef DEMONSTRATE_PCL
  +    co_resume();
  +#endif
  +
  +#ifdef DEMONSTRATE_PTHREAD
  +    pthread_mutex_unlock(&main_coroutine_lock);
  +    pthread_mutex_lock(&ruby_coroutine_lock);
  +#endif
  +
  +#ifdef DEMONSTRATE_UCONTEXT
  +    swapcontext(&ruby_coroutine, &main_coroutine);
  +#endif
  +
  +    printf("Relay: ruby <= main\n");
  +    return Qnil;
  +}
  +
  +static VALUE ruby_coroutine_body_require(const char* file)
  +{
  +    int error;
  +    VALUE result = rb_protect((VALUE (*)(VALUE))rb_require,
  +                              (VALUE)file, &error);
  +
  +    if (error)
  +    {
  +        printf("rb_require('%s') failed with status=%d\n",
  +               file, error);
  +
  +        VALUE exception = rb_gv_get("$!");
  +        if (RTEST(exception))
  +        {
  +            printf("... because an exception was raised:\n");
  +            fflush(stdout);
  +
  +            VALUE inspect = rb_inspect(exception);
  +            rb_io_puts(1, &inspect, rb_stderr);
  +
  +            VALUE backtrace = rb_funcall(
  +                exception, rb_intern("backtrace"), 0);
  +            rb_io_puts(1, &backtrace, rb_stderr);
  +        }
  +    }
  +
  +    return result;
  +}
  +
  +static void ruby_coroutine_body(
  +#ifdef DEMONSTRATE_PTHREAD
  +    void* dummy_argument_that_is_not_used
  +#endif
  +)
  +{
  +#ifdef DEMONSTRATE_PTHREAD
  +    printf("Coroutine: waiting for initial asynchronous relay from main\n");
  +    relay_from_ruby_to_main(Qnil);
  +#endif
  +
  +    printf("Coroutine: begin\n");
  +
  +    int i;
  +    for (i = 0; i < 2; i++)
  +    {
  +        printf("Coroutine: relay %d\n", i);
  +        relay_from_ruby_to_main(Qnil);
  +    }
  +
  +    printf("Coroutine: Ruby begin\n");
  +
  +#ifdef HAVE_RUBY_SYSINIT
  +    int argc = 0;
  +    char** argv = {""};
  +    ruby_sysinit(&argc, &argv);
  +#endif
  +    {
  +#ifdef HAVE_RUBY_BIND_STACK
  +        ruby_bind_stack(
  +                /* lower memory address */
  +                (VALUE*)(ruby_coroutine_stack),
  +
  +                /* upper memory address */
  +                (VALUE*)(ruby_coroutine_stack + ruby_coroutine_stack_size)
  +        );
  +#endif
  +
  +        RUBY_INIT_STACK;
  +        ruby_init();
  +        ruby_init_loadpath();
  +
  +        /* allow Ruby script to relay */
  +        rb_define_module_function(rb_mKernel, "relay_from_ruby_to_main",
  +                                  relay_from_ruby_to_main, 0);
  +
  +        /* run the "hello world" Ruby script */
  +        printf("Ruby: require 'hello' begin\n");
  +        ruby_coroutine_body_require("./hello.rb");
  +        printf("Ruby: require 'hello' end\n");
  +
  +        ruby_cleanup(0);
  +    }
  +
  +    printf("Coroutine: Ruby end\n");
  +
  +    printf("Coroutine: end\n");
  +
  +    ruby_coroutine_finished = true;
  +    relay_from_ruby_to_main(Qnil);
  +
  +#ifdef DEMONSTRATE_PTHREAD
  +    pthread_exit(NULL);
  +#endif
  +}
  +
  +#ifdef RUBY_GLOBAL_SETUP
  +RUBY_GLOBAL_SETUP
  +#endif
  +
  +int main()
  +{
  +#ifdef DEMONSTRATE_STATIC
  +    ruby_coroutine_stack_size = sizeof(ruby_coroutine_stack);
  +#endif
  +
  +#ifdef DEMONSTRATE_DYNAMIC
  +    /* allocate the coroutine stack */
  +    ruby_coroutine_stack = malloc(ruby_coroutine_stack_size);
  +    if (!ruby_coroutine_stack)
  +    {
  +        fprintf(stderr, "Could not allocate %lu bytes!\n", ruby_coroutine_stack_size);
  +        return 1;
  +    }
  +#endif
  +
  +#ifdef DEMONSTRATE_PCL
  +    /* create coroutine to house Ruby */
  +    ruby_coroutine = co_create(ruby_coroutine_body, NULL,
  +            ruby_coroutine_stack, ruby_coroutine_stack_size);
  +#endif
  +
  +#ifdef DEMONSTRATE_PTHREAD
  +    /* initialize the relay mechanism */
  +    pthread_mutex_init(&ruby_coroutine_lock, NULL);
  +    pthread_mutex_lock(&ruby_coroutine_lock);
  +    pthread_mutex_init(&main_coroutine_lock, NULL);
  +    pthread_mutex_lock(&main_coroutine_lock);
  +
  +    /* create pthread to house Ruby */
  +    pthread_attr_t attr;
  +    pthread_attr_init(&attr);
  +
  +#ifdef HAVE_PTHREAD_ATTR_SETSTACK
  +    pthread_attr_setstack(&attr, ruby_coroutine_stack, ruby_coroutine_stack_size);
  +#else
  +    pthread_attr_setstackaddr(&attr, ruby_coroutine_stack);
  +    pthread_attr_setstacksize(&attr, ruby_coroutine_stack_size);
  +#endif
  +
  +    int error = pthread_create(&ruby_coroutine, &attr, &ruby_coroutine_body, NULL);
  +    if (error) {
  +        printf("ERROR: pthread_create() returned %d\n", error);
  +        return 1;
  +    }
  +#endif
  +
  +#ifdef DEMONSTRATE_UCONTEXT
  +    /* create System V context to house Ruby */
  +    ruby_coroutine.uc_link          = &main_coroutine;
  +    ruby_coroutine.uc_stack.ss_sp   = ruby_coroutine_stack;
  +    ruby_coroutine.uc_stack.ss_size = ruby_coroutine_stack_size;
  +    getcontext(&ruby_coroutine);
  +    makecontext(&ruby_coroutine, (void (*)(void)) ruby_coroutine_body, 0);
  +#endif
  +
  +    /* relay control to Ruby until it is finished */
  +    ruby_coroutine_finished = false;
  +    while (!ruby_coroutine_finished)
  +    {
  +        relay_from_main_to_ruby();
  +    }
  +
  +    printf("Main: Goodbye!\n");
  +    return 0;
  +}
  @@ .
Received on Sun Sep 19 20:59:02 2010
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.