[macruby-changes] [1930] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Thu Jun 25 21:21:04 PDT 2009
Revision: 1930
http://trac.macosforge.org/projects/ruby/changeset/1930
Author: lsansonetti at apple.com
Date: 2009-06-25 21:21:03 -0700 (Thu, 25 Jun 2009)
Log Message:
-----------
more work on MacRuby MT
Modified Paths:
--------------
MacRuby/branches/experimental/include/ruby/intern.h
MacRuby/branches/experimental/thread.c
MacRuby/branches/experimental/vm.cpp
MacRuby/branches/experimental/vm.h
Modified: MacRuby/branches/experimental/include/ruby/intern.h
===================================================================
--- MacRuby/branches/experimental/include/ruby/intern.h 2009-06-25 18:09:46 UTC (rev 1929)
+++ MacRuby/branches/experimental/include/ruby/intern.h 2009-06-26 04:21:03 UTC (rev 1930)
@@ -297,10 +297,6 @@
void rb_thread_polling(void);
void rb_thread_sleep(int);
void rb_thread_sleep_forever(void);
-VALUE rb_thread_stop(void);
-VALUE rb_thread_wakeup(VALUE);
-VALUE rb_thread_run(VALUE);
-VALUE rb_thread_kill(VALUE);
VALUE rb_thread_create(VALUE (*)(ANYARGS), void*);
void rb_thread_signal_raise(void *, int);
void rb_thread_signal_exit(void *);
@@ -608,6 +604,7 @@
/* time.c */
VALUE rb_time_new(time_t, long);
VALUE rb_time_nano_new(time_t, long);
+struct timeval rb_time_interval(VALUE num);
/* variable.c */
//VALUE rb_mod_name(VALUE);
VALUE rb_class_path(VALUE);
Modified: MacRuby/branches/experimental/thread.c
===================================================================
--- MacRuby/branches/experimental/thread.c 2009-06-25 18:09:46 UTC (rev 1929)
+++ MacRuby/branches/experimental/thread.c 2009-06-26 04:21:03 UTC (rev 1930)
@@ -1,3 +1,12 @@
+/*
+ * MacRuby implementation of Thread.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2009, Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Koichi Sasada
+ */
+
#include "ruby/ruby.h"
#include "ruby/node.h"
#include "vm.h"
@@ -2,7 +11,5 @@
-#include <pthread.h>
-
typedef struct rb_vm_mutex {
pthread_mutex_t mutex;
- pthread_t thread;
+ rb_vm_thread_t *thread;
} rb_vm_mutex_t;
@@ -56,7 +63,7 @@
}
static VALUE
-thread_initialize(VALUE thread, SEL sel, int argc, VALUE *argv)
+thread_initialize(VALUE thread, SEL sel, int argc, const VALUE *argv)
{
if (!rb_block_given_p()) {
rb_raise(rb_eThreadError, "must be called with a block");
@@ -65,21 +72,8 @@
assert(b != NULL);
rb_vm_thread_t *t = GetThreadPtr(thread);
- assert(t->body == NULL);
- GC_WB(&t->body, b);
+ rb_vm_thread_pre_init(t, b, argc, argv, rb_vm_create_vm());
- if (argc > 0) {
- t->argc = argc;
- GC_WB(&t->argv, xmalloc(sizeof(VALUE) * argc));
- int i;
- for (i = 0; i < argc; i++) {
- GC_WB(&t->argv[i], argv[i]);
- }
- }
-
- t->vm = rb_vm_create_vm();
- t->value = Qundef;
-
// Retain the Thread object to avoid a potential GC, the corresponding
// release is done in rb_vm_thread_run().
rb_objc_retain((void *)thread);
@@ -89,6 +83,8 @@
rb_sys_fail("pthread_create() failed");
}
+ //assert(pthread_detach(t->thread) == 0);
+
return thread;
}
@@ -148,7 +144,7 @@
}
rb_vm_thread_t *t = GetThreadPtr(self);
- pthread_join(t->thread, NULL);
+ assert(pthread_join(t->thread, NULL) == 0);
return self;
}
@@ -172,30 +168,12 @@
}
void
-rb_thread_sleep_forever()
-{
- // TODO
-}
-
-void
-rb_thread_wait_for(struct timeval time)
-{
- // TODO
-}
-
-void
rb_thread_polling(void)
{
// TODO
}
void
-rb_thread_sleep(int sec)
-{
- // TODO
-}
-
-void
rb_thread_schedule(void)
{
// TODO
@@ -224,9 +202,9 @@
*/
static VALUE
-thread_s_pass(VALUE klass)
+thread_s_pass(VALUE klass, SEL sel)
{
- // TODO
+ pthread_yield_np();
return Qnil;
}
@@ -258,9 +236,9 @@
/*
* call-seq:
- * thr.exit => thr or nil
- * thr.kill => thr or nil
- * thr.terminate => thr or nil
+ * thr.exit => thr
+ * thr.kill => thr
+ * thr.terminate => thr
*
* Terminates <i>thr</i> and schedules another thread to be run. If this thread
* is already marked to be killed, <code>exit</code> returns the
@@ -268,11 +246,16 @@
* the process.
*/
-VALUE
-rb_thread_kill(VALUE thread)
+static VALUE
+rb_thread_kill(VALUE thread, SEL sel)
{
- // TODO
- return Qnil;
+ rb_vm_thread_t *t = GetThreadPtr(thread);
+ if (t->status == THREAD_KILLED) {
+ // Already being killed!
+ return thread;
+ }
+ rb_vm_thread_cancel(t);
+ return thread;
}
/*
@@ -328,10 +311,10 @@
* hey!
*/
-VALUE
-rb_thread_wakeup(VALUE thread)
+static VALUE
+rb_thread_wakeup(VALUE thread, SEL sel)
{
- // TODO
+ rb_vm_thread_wakeup(GetThreadPtr(thread));
return Qnil;
}
@@ -354,11 +337,11 @@
* c
*/
-VALUE
-rb_thread_run(VALUE thread)
+static VALUE
+rb_thread_run(VALUE thread, SEL sel)
{
- // TODO
- return Qnil;
+ // On MacRuby, #wakeup and #run are the same.
+ return rb_thread_wakeup(thread, 0);
}
/*
@@ -379,10 +362,10 @@
* abc
*/
-VALUE
-rb_thread_stop(void)
+static VALUE
+rb_thread_stop(VALUE rcv, SEL sel)
{
- // TODO
+ rb_thread_sleep_forever();
return Qnil;
}
@@ -446,10 +429,9 @@
*/
static VALUE
-rb_thread_s_abort_exc(void)
+rb_thread_s_abort_exc(VALUE rcv, SEL sel)
{
- // TODO
- return Qnil;
+ return rb_vm_abort_on_exception() ? Qtrue : Qfalse;
}
/*
@@ -477,10 +459,10 @@
*/
static VALUE
-rb_thread_s_abort_exc_set(VALUE self, VALUE val)
+rb_thread_s_abort_exc_set(VALUE self, SEL sel, VALUE val)
{
- // TODO
- return Qnil;
+ rb_vm_set_abort_on_exception(RTEST(val));
+ return val;
}
/*
@@ -554,11 +536,30 @@
* Thread.current.status #=> "run"
*/
+static const char *
+rb_thread_status_cstr(VALUE thread)
+{
+ rb_vm_thread_t *t = GetThreadPtr(thread);
+ switch (t->status) {
+ case THREAD_ALIVE:
+ return "run";
+
+ case THREAD_SLEEP:
+ return "sleep";
+
+ case THREAD_KILLED:
+ return "abort";
+
+ case THREAD_DEAD:
+ return "dead";
+ }
+ return "unknown";
+}
+
static VALUE
-rb_thread_status(VALUE thread)
+rb_thread_status(VALUE thread, SEL sel)
{
- // TODO
- return Qnil;
+ return rb_str_new2(rb_thread_status_cstr(thread));
}
/*
@@ -574,10 +575,10 @@
*/
static VALUE
-rb_thread_alive_p(VALUE thread)
+rb_thread_alive_p(VALUE thread, SEL sel)
{
- // TODO
- return Qnil;
+ rb_vm_thread_status_t s = GetThreadPtr(thread)->status;
+ return s == THREAD_ALIVE || s == THREAD_SLEEP ? Qtrue : Qfalse;
}
/*
@@ -595,7 +596,8 @@
static VALUE
rb_thread_stop_p(VALUE thread)
{
- return Qnil;
+ rb_vm_thread_status_t s = GetThreadPtr(thread)->status;
+ return s == THREAD_DEAD || s == THREAD_SLEEP ? Qtrue : Qfalse;
}
/*
@@ -627,7 +629,7 @@
static VALUE
rb_thread_inspect(VALUE thread, SEL sel)
{
- const char *status = "unknown"; // TODO
+ const char *status = rb_thread_status_cstr(thread);
char buf[100];
snprintf(buf, sizeof buf, "#<%s:%p %s>", rb_obj_classname(thread),
@@ -1182,7 +1184,7 @@
rb_mutex_trylock(VALUE self, SEL sel)
{
if (pthread_mutex_trylock(&GetMutexPtr(self)->mutex) == 0) {
- GetMutexPtr(self)->thread = pthread_self();
+ GetMutexPtr(self)->thread = GetThreadPtr(rb_vm_current_thread());
return Qtrue;
}
return Qfalse;
@@ -1199,13 +1201,15 @@
static VALUE
rb_mutex_lock(VALUE self, SEL sel)
{
- pthread_t current = pthread_self();
+ rb_vm_thread_t *current = GetThreadPtr(rb_vm_current_thread());
rb_vm_mutex_t *m = GetMutexPtr(self);
if (m->thread == current) {
rb_raise(rb_eThreadError, "deadlock; recursive locking");
}
+ current->status = THREAD_SLEEP;
assert_ok(pthread_mutex_lock(&m->mutex));
+ current->status = THREAD_ALIVE;
m->thread = current;
return self;
@@ -1244,10 +1248,26 @@
*/
static VALUE
-mutex_sleep(int argc, VALUE *argv, VALUE self)
+mutex_sleep(VALUE self, SEL sel, int argc, VALUE *argv)
{
- // TODO
- return Qnil;
+ VALUE timeout;
+ rb_scan_args(argc, argv, "01", &timeout);
+
+ rb_mutex_unlock(self, 0);
+
+ time_t beg, end;
+ beg = time(0);
+
+ if (timeout == Qnil) {
+ rb_thread_sleep_forever();
+ }
+ else {
+ struct timeval t = rb_time_interval(timeout);
+ rb_thread_wait_for(t);
+ }
+
+ end = time(0) - beg;
+ return INT2FIX(end);
}
/*
@@ -1262,9 +1282,16 @@
mutex_synchronize(VALUE self, SEL sel)
{
rb_mutex_lock(self, 0);
+
// TODO catch exception
VALUE ret = rb_yield(Qundef);
- rb_mutex_unlock(self, 0);
+
+ if (rb_mutex_locked_p(self, 0) == Qtrue) {
+ // We only unlock the mutex if it's still locked, since it could have
+ // been unlocked in the block!
+ rb_mutex_unlock(self, 0);
+ }
+
return ret;
}
@@ -1297,32 +1324,32 @@
rb_define_singleton_method(rb_cThread, "fork", thread_start, -2);
rb_objc_define_method(*(VALUE *)rb_cThread, "main", rb_thread_s_main, 0);
rb_objc_define_method(*(VALUE *)rb_cThread, "current", thread_s_current, 0);
- rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
+ rb_objc_define_method(*(VALUE *)rb_cThread, "stop", rb_thread_stop, 0);
rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
- rb_define_singleton_method(rb_cThread, "pass", thread_s_pass, 0);
+ rb_objc_define_method(*(VALUE *)rb_cThread, "pass", thread_s_pass, 0);
rb_objc_define_method(*(VALUE *)rb_cThread, "list", rb_thread_list, 0);
- rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
- rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
+ rb_objc_define_method(*(VALUE *)rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
+ rb_objc_define_method(*(VALUE *)rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
rb_objc_define_method(rb_cThread, "initialize", thread_initialize, -1);
rb_define_method(rb_cThread, "raise", thread_raise_m, -1);
rb_objc_define_method(rb_cThread, "join", thread_join_m, -1);
rb_objc_define_method(rb_cThread, "value", thread_value, 0);
- rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
- rb_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
- rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
- rb_define_method(rb_cThread, "run", rb_thread_run, 0);
- rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
+ rb_objc_define_method(rb_cThread, "kill", rb_thread_kill, 0);
+ rb_objc_define_method(rb_cThread, "terminate", rb_thread_kill, 0);
+ rb_objc_define_method(rb_cThread, "exit", rb_thread_kill, 0);
+ rb_objc_define_method(rb_cThread, "run", rb_thread_run, 0);
+ rb_objc_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
rb_define_method(rb_cThread, "keys", rb_thread_keys, 0);
rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
- rb_define_method(rb_cThread, "status", rb_thread_status, 0);
- rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
- rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
+ rb_objc_define_method(rb_cThread, "status", rb_thread_status, 0);
+ rb_objc_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
+ rb_objc_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
@@ -1343,7 +1370,7 @@
rb_objc_define_method(rb_cMutex, "try_lock", rb_mutex_trylock, 0);
rb_objc_define_method(rb_cMutex, "lock", rb_mutex_lock, 0);
rb_objc_define_method(rb_cMutex, "unlock", rb_mutex_unlock, 0);
- rb_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
+ rb_objc_define_method(rb_cMutex, "sleep", mutex_sleep, -1);
rb_objc_define_method(rb_cMutex, "synchronize", mutex_synchronize, 0);
rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp 2009-06-25 18:09:46 UTC (rev 1929)
+++ MacRuby/branches/experimental/vm.cpp 2009-06-26 04:21:03 UTC (rev 1930)
@@ -186,6 +186,7 @@
{
running = false;
multithreaded = false;
+ abort_on_exception = false;
assert(pthread_mutex_init(&gl, 0) == 0);
@@ -697,6 +698,20 @@
}
extern "C"
+bool
+rb_vm_abort_on_exception(void)
+{
+ return GET_CORE()->get_abort_on_exception();
+}
+
+extern "C"
+void
+rb_vm_set_abort_on_exception(bool flag)
+{
+ GET_CORE()->set_abort_on_exception(flag);
+}
+
+extern "C"
void
rb_vm_set_const(VALUE outer, ID id, VALUE obj)
{
@@ -3695,7 +3710,10 @@
assert(argc > 0);
VALUE current_exception = GET_VM()->current_exception();
- assert(current_exception != Qnil);
+ if (current_exception == Qnil) {
+ // Not a Ruby exception...
+ return 0;
+ }
va_list ar;
unsigned char active = 0;
@@ -4241,13 +4259,41 @@
unlock();
rb_vm_thread_t *t = GetThreadPtr(thread);
+
+ const int code = pthread_mutex_destroy(&t->sleep_mutex);
+ if (code == EBUSY) {
+ // The mutex is already locked, which means we are being called from
+ // a cancellation point inside the wait logic. Let's unlock the mutex
+ // and try again.
+ assert(pthread_mutex_unlock(&t->sleep_mutex) == 0);
+ assert(pthread_mutex_destroy(&t->sleep_mutex) == 0);
+ }
+ else if (code != 0) {
+ abort();
+ }
+ assert(pthread_cond_destroy(&t->sleep_cond) == 0);
+
RoxorVM *vm = (RoxorVM *)t->vm;
delete vm;
t->vm = NULL;
assert(pthread_setspecific(RoxorVM::vm_thread_key, NULL) == 0);
+
+ t->status = THREAD_DEAD;
}
+static inline void
+rb_vm_thread_throw_kill(void)
+{
+ rb_vm_rethrow();
+}
+
+static void
+rb_vm_thread_destructor(void *userdata)
+{
+ rb_vm_thread_throw_kill();
+}
+
extern "C"
void *
rb_vm_thread_run(VALUE thread)
@@ -4255,24 +4301,30 @@
rb_objc_gc_register_thread();
GET_CORE()->register_thread(thread);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+
// Release the thread now.
rb_objc_release((void *)thread);
+ pthread_cleanup_push(rb_vm_thread_destructor, (void *)thread);
+
+ rb_vm_thread_t *t = GetThreadPtr(thread);
try {
- rb_vm_thread_t *t = GetThreadPtr(thread);
VALUE val = rb_vm_block_eval(t->body, t->argc, t->argv);
GC_WB(&t->value, val);
}
catch (...) {
// TODO handle thread-level exceptions.
- printf("exception raised inside thread %p\n", pthread_self());
+ //printf("exception raised inside thread %p\n", pthread_self());
}
+ pthread_cleanup_pop(0);
+
GET_CORE()->unregister_thread(thread);
rb_objc_gc_unregister_thread();
return NULL;
-
}
extern "C"
@@ -4296,6 +4348,118 @@
return RoxorVM::main->get_thread();
}
+extern "C"
+void
+rb_vm_thread_pre_init(rb_vm_thread_t *t, rb_vm_block_t *body, int argc,
+ const VALUE *argv, void *vm)
+{
+ t->thread = 0; // this will be set later
+
+ if (body != NULL) {
+ GC_WB(&t->body, body);
+ }
+ else {
+ t->body = NULL;
+ }
+
+ if (argc > 0) {
+ t->argc = argc;
+ GC_WB(&t->argv, xmalloc(sizeof(VALUE) * argc));
+ int i;
+ for (i = 0; i < argc; i++) {
+ GC_WB(&t->argv[i], argv[i]);
+ }
+ }
+ else {
+ t->argc = 0;
+ t->argv = NULL;
+ }
+
+ t->vm = vm;
+ t->value = Qundef;
+ t->status = THREAD_ALIVE;
+
+ assert(pthread_mutex_init(&t->sleep_mutex, NULL) == 0);
+ assert(pthread_cond_init(&t->sleep_cond, NULL) == 0);
+}
+
+extern "C"
+void
+rb_thread_sleep_forever()
+{
+ rb_vm_thread_t *t = GET_THREAD();
+ t->status = THREAD_SLEEP;
+
+ assert(pthread_mutex_lock(&t->sleep_mutex) == 0);
+ const int code = pthread_cond_wait(&t->sleep_cond, &t->sleep_mutex);
+ assert(code == 0 || code == ETIMEDOUT);
+ assert(pthread_mutex_unlock(&t->sleep_mutex) == 0);
+
+ t->status = THREAD_ALIVE;
+}
+
+extern "C"
+void
+rb_thread_wait_for(struct timeval time)
+{
+ struct timeval tvn;
+ gettimeofday(&tvn, NULL);
+
+ struct timespec ts;
+ ts.tv_sec = tvn.tv_sec + time.tv_sec;
+ ts.tv_nsec = (tvn.tv_usec + time.tv_usec) * 1000;
+ while (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec += 1;
+ ts.tv_nsec -= 1000000000;
+ }
+
+ rb_vm_thread_t *t = GET_THREAD();
+ t->status = THREAD_SLEEP;
+
+ assert(pthread_mutex_lock(&t->sleep_mutex) == 0);
+ const int code = pthread_cond_timedwait(&t->sleep_cond, &t->sleep_mutex,
+ &ts);
+ assert(code == 0 || code == ETIMEDOUT);
+ assert(pthread_mutex_unlock(&t->sleep_mutex) == 0);
+
+ t->status = THREAD_ALIVE;
+}
+
+extern "C"
+void
+rb_vm_thread_wakeup(rb_vm_thread_t *t)
+{
+ if (t->status == THREAD_DEAD) {
+ rb_raise(rb_eThreadError, "can't wake up thread from the dead");
+ }
+ if (t->status == THREAD_SLEEP) {
+ assert(pthread_cond_signal(&t->sleep_cond) == 0);
+ }
+}
+
+extern "C"
+void
+rb_vm_thread_cancel(rb_vm_thread_t *t)
+{
+ t->status = THREAD_KILLED;
+ if (t->thread == pthread_self()) {
+ rb_vm_thread_throw_kill();
+ }
+ else {
+ assert(pthread_cancel(t->thread) == 0);
+ }
+}
+
+extern "C"
+void
+rb_thread_sleep(int sec)
+{
+ struct timeval time;
+ time.tv_sec = sec;
+ time.tv_usec = 0;
+ rb_thread_wait_for(time);
+}
+
static VALUE
builtin_ostub1(IMP imp, id self, SEL sel, int argc, VALUE *argv)
{
@@ -4384,11 +4548,13 @@
Init_PostVM(void)
{
// Create and register the main thread;
+ RoxorVM *main_vm = GET_VM();
rb_vm_thread_t *t = (rb_vm_thread_t *)xmalloc(sizeof(rb_vm_thread_t));
+ rb_vm_thread_pre_init(t, NULL, 0, NULL, (void *)main_vm);
t->thread = pthread_self();
- t->vm = (void *)GET_VM();
VALUE main = Data_Wrap_Struct(rb_cThread, NULL, NULL, t);
GET_CORE()->register_thread(main);
+ main_vm->set_thread(main);
}
extern "C"
Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h 2009-06-25 18:09:46 UTC (rev 1929)
+++ MacRuby/branches/experimental/vm.h 2009-06-26 04:21:03 UTC (rev 1930)
@@ -71,6 +71,15 @@
#define GetThreadPtr(obj) ((rb_vm_thread_t *)DATA_PTR(obj))
+typedef enum {
+ THREAD_ALIVE, // this thread was born to be alive
+ THREAD_SLEEP, // this thread is sleeping
+ THREAD_KILLED, // this thread is being killed!
+ THREAD_DEAD // this thread is dead, sigh
+} rb_vm_thread_status_t;
+
+#include <pthread.h>
+
typedef struct rb_vm_thread {
pthread_t thread;
rb_vm_block_t *body;
@@ -78,6 +87,9 @@
const VALUE *argv;
void *vm; // an instance of RoxorVM
VALUE value;
+ pthread_mutex_t sleep_mutex;
+ pthread_cond_t sleep_cond;
+ rb_vm_thread_status_t status;
} rb_vm_thread_t;
typedef struct rb_vm_outer {
@@ -323,12 +335,19 @@
void rb_vm_add_binding(rb_vm_binding_t *binding);
void rb_vm_pop_binding();
+void rb_vm_thread_pre_init(rb_vm_thread_t *t, rb_vm_block_t *body, int argc,
+ const VALUE *argv, void *vm);
void *rb_vm_create_vm(void);
void *rb_vm_thread_run(VALUE thread);
VALUE rb_vm_current_thread(void);
VALUE rb_vm_main_thread(void);
VALUE rb_vm_threads(void);
+void rb_vm_thread_wakeup(rb_vm_thread_t *t);
+void rb_vm_thread_cancel(rb_vm_thread_t *t);
+bool rb_vm_abort_on_exception(void);
+void rb_vm_set_abort_on_exception(bool flag);
+
static inline VALUE
rb_robject_allocate_instance(VALUE klass)
{
@@ -360,6 +379,7 @@
VALUE rb_vm_pop_broken_value(void);
#define RETURN_IF_BROKEN() \
do { \
+ pthread_testcancel(); \
VALUE __v = rb_vm_pop_broken_value(); \
if (__v != Qundef) { \
return __v; \
@@ -472,6 +492,7 @@
// State.
bool running;
bool multithreaded;
+ bool abort_on_exception;
pthread_mutex_t gl;
VALUE loaded_features;
VALUE load_path;
@@ -525,6 +546,7 @@
ACCESSOR(running, bool);
ACCESSOR(multithreaded, bool);
+ ACCESSOR(abort_on_exception, bool);
READER(loaded_features, VALUE);
READER(load_path, VALUE);
READER(threads, VALUE);
@@ -826,6 +848,7 @@
};
#define GET_VM() (RoxorVM::current())
+#define GET_THREAD() (GetThreadPtr(GET_VM()->get_thread()))
#endif /* __cplusplus */
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090625/5b1930c6/attachment-0001.html>
More information about the macruby-changes
mailing list