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