yarv-diff:112
From: ko1 atdot.net
Date: 30 Sep 2005 11:12:25 -0000
Subject: [yarv-diff:112] r268 - trunk
Author: ko1
Date: 2005-09-30 20:12:25 +0900 (Fri, 30 Sep 2005)
New Revision: 268
Modified:
trunk/ChangeLog
trunk/test.rb
trunk/thread.c
trunk/yarvcore.h
Log:
* thread.c : support join with timeout
* yarvcore.h : use GET_VM()
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-09-30 06:08:45 UTC (rev 267)
+++ trunk/ChangeLog 2005-09-30 11:12:25 UTC (rev 268)
@@ -4,6 +4,13 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2005-09-30(Fri) 20:11:19 +0900 Koichi Sasada <ko1 atdot.net>
+
+ * thread.c : support join with timeout
+
+ * yarvcore.h : use GET_VM()
+
+
2005-09-30(Fri) 14:59:29 +0900 Koichi Sasada <ko1 atdot.net>
* thread.c, common.mk : add thread.c
Modified: trunk/test.rb
===================================================================
--- trunk/test.rb 2005-09-30 06:08:45 UTC (rev 267)
+++ trunk/test.rb 2005-09-30 11:12:25 UTC (rev 268)
@@ -1,4 +1,11 @@
+Thread.new{
+ sleep
+}.join(10)
+
+p :finish
+exit
+__END__
10.times{|e|
Thread.new(e){|le|
10000.times{|i|
Modified: trunk/thread.c
===================================================================
--- trunk/thread.c 2005-09-30 06:08:45 UTC (rev 267)
+++ trunk/thread.c 2005-09-30 11:12:25 UTC (rev 268)
@@ -48,6 +48,10 @@
#define thead_debug if(0)printf
#endif
+static void sleep_for_polling();
+static void sleep_timeval(struct timeval time);
+static double timeofday();
+struct timeval rb_time_interval(VALUE);
/********************************************************************************/
@@ -157,15 +161,42 @@
if(th->status == THREAD_KILLED){
return self;
}
-
- GIL_UNLOCK_BEGIN();
- err = native_thread_join(th->thread_id, 0);
- GIL_UNLOCK_END();
- switch(err){
- case EDEADLK:
- rb_raise(rb_eThreadError, "can't join current thread (cause dead lock)");
+ if(argc == 0){
+ GIL_UNLOCK_BEGIN();
+ err = native_thread_join(th->thread_id, 0);
+ GIL_UNLOCK_END();
+
+ switch(err){
+ case EDEADLK:
+ rb_raise(rb_eThreadError, "can't join current thread (cause dead lock)");
+ }
}
+ else if(argc == 1){
+ double limit = timeofday();
+ struct timeval interval;
+
+ interval = rb_time_interval(argv[0]);
+ limit += interval.tv_sec;
+ limit += interval.tv_usec * 1e-6;
+
+ while(1){
+ GIL_UNLOCK_BEGIN();
+ sleep_for_polling();
+ GIL_UNLOCK_END();
+
+ if(th->status == THREAD_KILLED){
+ break;
+ }
+ if(timeofday() > limit){
+ /* timeout */
+ return Qnil;
+ }
+ }
+ }
+ else{
+
+ }
return self;
}
@@ -237,6 +268,14 @@
}
}
+static void
+sleep_for_polling(){
+ struct timeval time;
+ time.tv_sec = 0;
+ time.tv_usec = 100000; /* 0.1 sec */
+ sleep_timeval(time);
+}
+
void
rb_thread_wait_for(struct timeval time)
{
@@ -249,6 +288,54 @@
CSL_UNLOCK_END();
}
+void
+yarv_thraed_schedule()
+{
+ if(GET_VM()->thread_critical == 0){
+ yarv_thread_t *th = GET_THREAD();
+ yarv_save_machine_context(th);
+ native_mutex_unlock(&GET_VM()->global_interpreter_lock);
+ native_mutex_lock(&GET_VM()->global_interpreter_lock);
+ yarv_set_current_running_thread(th);
+ }
+}
+
+#if HAVE_PTHREAD_H
+static pthread_t time_thread;
+
+static void*
+thread_timer(void *dummy)
+{
+ while(1){
+#ifdef HAVE_NANOSLEEP
+ struct timespec req, rem;
+
+ req.tv_sec = 0;
+ req.tv_nsec = 10000000;
+ nanosleep(&req, &rem);
+#else
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+ select(0, NULL, NULL, NULL, &tv);
+#endif
+ GET_VM()->interrupt_flag = 1;
+ }
+}
+
+void make_timer_thread()
+{
+ if(!time_thread){
+ pthread_create(&time_thread, 0, thread_timer, 0);
+ }
+}
+
+#else
+#error "unsupported"
+#endif /* HAVE_PTHREAD_H */
+
+/********************************************************************/
+
static VALUE
yarv_thread_s_current(VALUE klass){
return GET_THREAD()->self;
@@ -259,7 +346,6 @@
return GET_VM()->main_thread;
}
-
VALUE
rb_thread_local_aref(VALUE thread, ID id)
{
@@ -279,7 +365,6 @@
return Qnil;
}
-
/*
* call-seq:
* thr[sym] => obj or nil
@@ -339,12 +424,11 @@
*/
static VALUE
-rb_thread_aset(VALUE thread, ID id, VALUE val)
+rb_thread_aset(VALUE self, ID id, VALUE val)
{
- return rb_thread_local_aset(thread, rb_to_id(id), val);
+ return rb_thread_local_aset(self, rb_to_id(id), val);
}
-
/*
* call-seq:
* thr.key?(sym) => true or false
@@ -359,10 +443,10 @@
*/
static VALUE
-rb_thread_key_p(VALUE thread, ID id)
+rb_thread_key_p(VALUE self, ID id)
{
yarv_thread_t *th;
- GetThreadVal(thread, th);
+ GetThreadVal(self, th);
if(!th->local_storage){
return Qfalse;
@@ -396,11 +480,10 @@
*/
static VALUE
-rb_thread_keys(thread)
- VALUE thread;
+rb_thread_keys(VALUE self)
{
yarv_thread_t *th;
- GetThreadVal(thread, th);
+ GetThreadVal(self, th);
VALUE ary = rb_ary_new();
if(th->local_storage){
@@ -409,18 +492,6 @@
return ary;
}
-void
-yarv_thraed_schedule()
-{
- if(GET_VM()->thread_critical == 0){
- yarv_thread_t *th = GET_THREAD();
- yarv_save_machine_context(th);
- native_mutex_unlock(&GET_VM()->global_interpreter_lock);
- native_mutex_lock(&GET_VM()->global_interpreter_lock);
- yarv_set_current_running_thread(th);
- }
-}
-
static VALUE
yarv_thread_s_pass(VALUE klass)
{
@@ -442,28 +513,7 @@
setjmp(th->machine_regs);
}
-static pthread_t time_thread;
-static void*
-thread_timer(void *dummy)
-{
- for (;;) {
-#ifdef HAVE_NANOSLEEP
- struct timespec req, rem;
-
- req.tv_sec = 0;
- req.tv_nsec = 10000000;
- nanosleep(&req, &rem);
-#else
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 10000;
- select(0, NULL, NULL, NULL, &tv);
-#endif
- theYarvVM->interrupt_flag = 1;
- }
-}
-
void
Init_yarvthread(){
rb_define_singleton_method(cYarvThread, "new", yarv_thread_s_new, -2);
@@ -480,9 +530,7 @@
rb_define_method(cYarvThread, "key?", rb_thread_key_p, 1);
rb_define_method(cYarvThread, "keys", rb_thread_keys, 0);
- if(time_thread == 0){
- pthread_create(&time_thread, 0, thread_timer, 0);
- }
+ make_timer_thread();
{
/* main thread setting */
Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h 2005-09-30 06:08:45 UTC (rev 267)
+++ trunk/yarvcore.h 2005-09-30 11:12:25 UTC (rev 268)
@@ -486,8 +486,8 @@
void yarv_thraed_schedule();
#define YARV_CHECK_INTS() do { \
- if(theYarvVM->interrupt_flag){ \
- theYarvVM->interrupt_flag = 0; \
+ if(GET_VM()->interrupt_flag){ \
+ GET_VM()->interrupt_flag = 0; \
/* TODO: trap something event */ \
yarv_thraed_schedule(); \
} \
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml