[#30549] [ANN] Ruby 1.8.6 has been released — "Akinori MUSHA" <knu@...>

 Ruby 1.8.6 をリリースしました。

14 messages 2007/03/12

[#30553] help: lib/shell for ruby 1.9 — keiju@... (Keiju ISHITSUKA)

けいじゅ@いしつかです.

13 messages 2007/03/13
[#30585] Re: help: lib/shell for ruby 1.9 — Yukihiro Matsumoto <matz@...> 2007/03/15

まつもと ゆきひろです

[#30587] Re: help: lib/shell for ruby 1.9 — keiju@... (石塚圭樹) 2007/03/15

けいじゅ@いしつかです.

[#30588] Re: help: lib/shell for ruby 1.9 — Yukihiro Matsumoto <matz@...> 2007/03/15

まつもと ゆきひろです

[ruby-dev:30646] Re: [ruby-core:10580] Thread後のexecでENOTSUPPエラー対応

From: Nobuyoshi Nakada <nobu@...>
Date: 2007-03-19 17:03:56 UTC
List: ruby-dev #30646
なかだです。

At Wed, 14 Mar 2007 21:26:31 +0900,
H.Holon wrote in [ruby-dev:30581]:
> +#ifdef _THREAD_SAFE
> +    pthread_testcancel();
> +#endif
>  #ifdef HAVE_NANOSLEEP
>  	struct timespec req, rem;

この位置だと変数宣言よりも前に実行文を追加することになるのでま
ずいです。

もう一点、この方法ではtestcancelに入るまで中断させることができ
ません。nanosleepやselectとの組合せよりも、cancel pointである
pthread_cond_timedwait()あたりを使ったほうがよくはないでしょう
か。

eval.cの分だけ。


Index: eval.c
===================================================================
--- eval.c	(revision 12059)
+++ eval.c	(working copy)
@@ -11737,5 +11737,9 @@ catch_timer(sig)
 }
 
-static pthread_t time_thread;
+static struct {
+    pthread_t thid;
+    pthread_mutex_t lock;
+    pthread_cond_t cond;
+} timer;
 
 static void*
@@ -11743,17 +11747,41 @@ thread_timer(dummy)
     void *dummy;
 {
-    for (;;) {
-#ifdef HAVE_NANOSLEEP
-	struct timespec req, rem;
+#define PER_NANO 1000000000
 
-	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
+#define cleanup_start(v, t, i, d) \
+    pthread_cleanup_push((void (*)_((void *)))pthread_##t##_##d, v);\
+    pthread_##t##_##i
+#define cleanup_end() pthread_cleanup_pop(1)
+
+    struct timespec to;
+    struct timeval tv;
+
+    /* count from the thread creation */
+    gettimeofday(&tv, NULL);
+    to.tv_sec = tv.tv_sec;
+    to.tv_nsec = tv.tv_usec * 1000;
+
+    cleanup_start(&timer.cond, cond, init, destroy)(&timer.cond, NULL);
+    cleanup_start(&timer.lock, mutex, init, destroy)(&timer.lock, NULL);
+    cleanup_start(&timer.lock, mutex, lock, unlock)(&timer.lock);
+
+    for (;;) {
+	/* 0.01sec future */
+	if ((to.tv_nsec += PER_NANO / 100) >= PER_NANO) {
+	    to.tv_sec += to.tv_nsec / PER_NANO;
+	    to.tv_nsec %= PER_NANO;
+	}
+	gettimeofday(&tv, NULL);
+	if ((tv.tv_sec < to.tv_sec) ||
+	    (tv.tv_sec == to.tv_sec && tv.tv_usec <= to.tv_nsec * 1000)) {
+	    /* has past already */
+	    to.tv_sec = tv.tv_sec;
+	    to.tv_nsec = tv.tv_usec * 1000;
+	    continue;
+	}
+	if (!pthread_cond_timedwait(&timer.cond, &timer.lock, &to)) {
+	    /* cancel request */
+	    break;
+	}
 	if (!rb_thread_critical) {
 	    rb_thread_pending = 1;
@@ -11763,4 +11791,8 @@ thread_timer(dummy)
 	}
     }
+
+    cleanup_end();
+    cleanup_end();
+    cleanup_end();
 }
 
@@ -11774,4 +11806,14 @@ rb_thread_stop_timer()
 {
 }
+
+void
+rb_thread_cancel_timer()
+{
+    if (!thread_init) return;
+    pthread_mutex_lock(&timer.lock);
+    pthread_cond_signal(&timer.cond);
+    pthread_mutex_unlock(&timer.lock);
+    thread_init = 0;
+}
 #elif defined(HAVE_SETITIMER)
 static void
@@ -11811,4 +11853,10 @@ rb_thread_stop_timer()
     setitimer(ITIMER_VIRTUAL, &tval, NULL);
 }
+
+void
+rb_thread_cancel_timer()
+{
+    thread_init = 0;
+}
 #else  /* !(_THREAD_SAFE || HAVE_SETITIMER) */
 int rb_thread_tick = THREAD_TICK;


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread