[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:330

From: ko1 atdot.net
Date: 7 May 2006 12:20:19 -0000
Subject: [yarv-diff:330] r497 - in trunk: . lib lib/webrick

Author: ko1
Date: 2006-05-07 21:20:19 +0900 (Sun, 07 May 2006)
New Revision: 497

Modified:
   trunk/
   trunk/ChangeLog
   trunk/lib/monitor.rb
   trunk/lib/thread.rb
   trunk/lib/webrick/server.rb
   trunk/thread.c
   trunk/thread_pthread.h
   trunk/thread_win32.h
   trunk/yarvcore.h
Log:
 r770@lermite:  ko1 | 2006-05-07 21:17:47 +0900
 	* thread.c : remove Mutex#unlock_and_stop and add Mutex#sleep
 
 	* lib/monitor.rb : ditto
 
 	* lib/thread.rb : ditto
 
 	* thread_pthread.h : fix stack size
 
 	* thread_win32.h : fix sleep
 
 	* yarvcore.h : disable to use get/setcontext
 
 	* lib/webrick/server.rb : add experimental implementation 
 	using thraeds pool
 



Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:768
   + 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:770

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/ChangeLog	2006-05-07 12:20:19 UTC (rev 497)
@@ -4,6 +4,24 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-05-07(Sun) 21:06:28 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* thread.c : remove Mutex#unlock_and_stop and add Mutex#sleep
+
+	* lib/monitor.rb : ditto
+
+	* lib/thread.rb : ditto
+
+	* thread_pthread.h : fix stack size
+
+	* thread_win32.h : fix sleep
+
+	* yarvcore.h : disable to use get/setcontext
+
+	* lib/webrick/server.rb : add experimental implementation 
+	using thraeds pool
+
+
 2006-05-05(Fri) 13:59:00 +0900  Koichi Sasada  <ko1 atdot.net>
 
 	* test/ruby/test_signal.rb : disable a test

Modified: trunk/lib/monitor.rb
===================================================================
--- trunk/lib/monitor.rb	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/lib/monitor.rb	2006-05-07 12:20:19 UTC (rev 497)
@@ -90,26 +90,28 @@
     def wait(timeout = nil)
       @monitor.funcall(:mon_check_owner)
       timer = create_timer(timeout)
-      
-      @mutex.lock
-      count = @monitor.funcall(:mon_exit_for_cond)
-      @waiters.push(Thread.current)
 
-      begin
-        @mutex.unlock_and_stop
-        return true
-      rescue Timeout
-        return false
-      ensure
-	@mutex.synchronize {
-          if timer && timer.alive?
-            Thread.kill(timer)
-          end
-          if @waiters.include?(Thread.current)  # interrupted?
-            @waiters.delete(Thread.current)
-          end
-          @monitor.funcall(:mon_enter_for_cond, count)
-        }
+      @mutex.synchronize{
+        count = @monitor.funcall(:mon_exit_for_cond)
+        @waiters.push(Thread.current)
+
+        begin
+          @mutex.sleep
+          return true
+        rescue Timeout
+          return false
+        end
+      }
+    ensure
+      @mutex.synchronize {
+        if timer && timer.alive?
+          Thread.kill(timer)
+        end
+        if @waiters.include?(Thread.current)  # interrupted?
+          @waiters.delete(Thread.current)
+        end
+        @monitor.funcall(:mon_enter_for_cond, count)
+      }
       end
     end
     
@@ -163,7 +165,6 @@
 	return Thread.start {
 	  Thread.pass
 	  sleep(timeout)
-	  #Thread.critical = true
 	  waiter.raise(Timeout.new)
 	}
       else

Modified: trunk/lib/thread.rb
===================================================================
--- trunk/lib/thread.rb	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/lib/thread.rb	2006-05-07 12:20:19 UTC (rev 497)
@@ -72,9 +72,7 @@
     begin
       # TODO: mutex should not be used
       @waiters.push(Thread.current)
-      mutex.unlock_and_stop
-    ensure
-      mutex.lock
+      mutex.sleep
     end
   end
   
@@ -190,8 +188,7 @@
         if @que.empty?
           raise ThreadError, "queue empty" if non_block
           @waiting.push Thread.current
-          @mutex.unlock_and_stop
-          @mutex.lock
+          @mutex.sleep
         else
           return @que.shift
         end
@@ -299,22 +296,24 @@
   # until space becomes available.
   #
   def push(obj)
-    while true
-      @mutex.lock
-      break if @que.length <= @max
-      @queue_wait.push Thread.current
-      @mutex.unlock_and_stop
-    end
-    @que.push obj
+    t = nil
+    @mutex.synchronize{
+      while true
+        break if @que.length <= @max
+        @queue_wait.push Thread.current
+        @mutex.sleep
+      end
+    
+      @que.push obj
+      begin
+        t = @waiting.shift
+        t.wakeup if t
+      rescue ThreadError
+        retry
+      end
+    }
+    
     begin
-      t = @waiting.shift
-      t.wakeup if t
-    rescue ThreadError
-      retry
-    end
-  ensure
-    @mutex.unlock
-    begin
       t.run if t
     rescue ThreadError
     end

Modified: trunk/lib/webrick/server.rb
===================================================================
--- trunk/lib/webrick/server.rb	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/lib/webrick/server.rb	2006-05-07 12:20:19 UTC (rev 497)
@@ -198,3 +198,102 @@
     end
   end    # end of GenericServer
 end
+
+
+if defined? WEBrick2
+#
+p :WEBrick2
+module WEBrick
+  class GenericServer
+
+    alias old_initialize initialize
+    
+    def initialize(config={}, default=Config::General)
+      old_initialize(config, default)
+
+      @client_requests = SizedQueue.new(@config[:MaxClients])
+      @thgroup = ThreadGroup.new
+      
+      @thread_pool = @config[:MaxClients].times{
+        Thread.new{
+          @thgroup.add(Thread.current)
+
+          while @status != :Shutdown
+            sock, block = @client_requests.pop
+            break unless sock
+
+            Thread.current[:WEBrickThread] = true
+
+            begin
+              Thread.current[:WEBrickSocket] = sock
+              begin
+                addr = sock.peeraddr
+                @logger.debug "accept: #{addr[3]}:#{addr[1]}"
+              rescue SocketError
+                @logger.debug "accept: <address unknown>"
+                raise
+              end
+              call_callback(:AcceptCallback, sock)
+              block ? block.call(sock) : run(sock)
+            rescue Errno::ENOTCONN
+              @logger.debug "Errno::ENOTCONN raised"
+            rescue ServerError => ex
+              msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+              @logger.error msg
+            rescue Exception => ex
+              @logger.error ex
+            ensure
+              Thread.current[:WEBrickSocket] = nil
+              Thread.current[:WEBrickThread] = false
+              
+              if addr
+                @logger.debug "close: #{addr[3]}:#{addr[1]}"
+              else
+                @logger.debug "close: <address unknown>"
+              end
+              sock.close
+            end
+          end
+        }
+      }
+    end
+
+    def start(&block)
+      raise ServerError, "already started." if @status != :Stop
+      server_type = @config[:ServerType] || SimpleServer
+
+      server_type.start{
+        @logger.info \
+          "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
+        call_callback(:StartCallback)
+
+        thgroup = ThreadGroup.new
+        @status = :Running
+        while @status == :Running
+          begin
+            if svrs = IO.select(@listeners, nil, nil, 2.0)
+              svrs[0].each{|svr|
+                if sock = accept_client(svr)
+                  @client_requests.push [sock, block]
+                end
+              }
+            end
+          rescue Errno::EBADF, IOError => ex
+            # if the listening socket was closed in GenericServer#shutdown,
+            # IO::select raise it.
+          rescue Exception => ex
+            msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+            @logger.error msg
+          end
+        end
+
+        @logger.info "going to shutdown ..."
+        @thgroup.list.each{|th| th.join if th[:WEBrickThread] }
+        call_callback(:StopCallback)
+        @logger.info "#{self.class}#start done."
+        @status = :Stop
+      }
+    end
+  end
+end
+end

Modified: trunk/thread.c
===================================================================
--- trunk/thread.c	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/thread.c	2006-05-07 12:20:19 UTC (rev 497)
@@ -224,7 +224,6 @@
 
 VALUE th_eval_body(yarv_thread_t *th);
 
-
 static void
 thread_cleanup_func(void *th_ptr)
 {
@@ -1503,7 +1502,6 @@
 #endif
 
 #ifndef linux
-
     if (timeout) {
 	tv = *timeout;
 	tvp = &tv;
@@ -1511,6 +1509,7 @@
 #else
     tvp = timeout;
 #endif
+
     for (;;) {
 	GVL_UNLOCK_RANGE(n = select(max, read, write, except, tvp);
 			 lerrno = errno;
@@ -1885,11 +1884,24 @@
 }
 
 static VALUE
-mutex_unlock_and_stop(VALUE self)
+mutex_sleep(int argc, VALUE *argv, VALUE self)
 {
+    int beg, end;
     mutex_unlock(self);
-    rb_thread_sleep_forever();
-    return self;
+
+    beg = time(0);
+    if (argc == 0) {
+	rb_thread_sleep_forever();
+    }
+    else if (argc == 1) {
+	rb_thread_wait_for(rb_time_interval(argv[0]));
+    }
+    else {
+	rb_raise(rb_eArgError, "wrong number of arguments");
+    }
+    mutex_lock(self);
+    end = time(0) - beg;
+    return INT2FIX(end);
 }
 
 
@@ -1960,7 +1972,7 @@
     rb_define_method(cMutex, "try_lock", mutex_try_lock, 0);
     rb_define_method(cMutex, "lock", mutex_lock, 0);
     rb_define_method(cMutex, "unlock", mutex_unlock, 0);
-    rb_define_method(cMutex, "unlock_and_stop", mutex_unlock_and_stop, 0);
+    rb_define_method(cMutex, "sleep", mutex_sleep, -1);
 
     Init_native_thread();
     {

Modified: trunk/thread_pthread.h
===================================================================
--- trunk/thread_pthread.h	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/thread_pthread.h	2006-05-07 12:20:19 UTC (rev 497)
@@ -157,19 +157,22 @@
     int result = 0;
 #if USE_THREAD_CACHE
     struct cached_thread_entry *entry;
-    pthread_mutex_lock(&thread_cache_lock);
-    entry = cached_thread_root;
-    {
-	if (cached_thread_root) {
-	    cached_thread_root = entry->next;
-	    *entry->th_area = th;
-	    result = 1;
+
+    if (cached_thread_root) {
+	pthread_mutex_lock(&thread_cache_lock);
+	entry = cached_thread_root;
+	{
+	    if (cached_thread_root) {
+		cached_thread_root = entry->next;
+		*entry->th_area = th;
+		result = 1;
+	    }
 	}
+	if (result) {
+	    pthread_cond_signal(entry->cond);
+	}
+	pthread_mutex_unlock(&thread_cache_lock);
     }
-    if (result) {
-	pthread_cond_signal(entry->cond);
-    }
-    pthread_mutex_unlock(&thread_cache_lock);
 #endif
     return result;
 }
@@ -184,8 +187,12 @@
     }
     else {
 	pthread_attr_t attr;
-	size_t stack_size = 4 * 1024 - sizeof(int);	/* 4KB */
+	size_t stack_size = 512 * 1024 - sizeof(int);	/* 512KB */
 
+	if (stack_size < PTHREAD_STACK_MIN) {
+	    stack_size = PTHREAD_STACK_MIN * 2;
+	}
+	
 	thread_debug("create: %p, stack size: %ld\n", th, stack_size);
 
 	pthread_attr_init(&attr);
@@ -405,7 +412,13 @@
 make_timer_thread()
 {
     if (!time_thread) {
-	pthread_create(&time_thread, 0, thread_timer, 0);
+	size_t stack_size = PTHREAD_STACK_MIN;
+	pthread_attr_t attr;
+	
+	pthread_attr_init(&attr);
+	pthread_attr_setstacksize(&attr, stack_size);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	pthread_create(&time_thread, &attr, thread_timer, 0);
     }
 }
 

Modified: trunk/thread_win32.h
===================================================================
--- trunk/thread_win32.h	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/thread_win32.h	2006-05-07 12:20:19 UTC (rev 497)
@@ -83,10 +83,10 @@
     if (th) {
 	HANDLE intr = th->native_thread_data.interrupt_event;
 	ResetEvent(intr);
-	
 	if (th->interrupt_flag) {
 	    SetEvent(intr);
 	}
+
 	events[count++] = intr;
 	thread_debug("  * handle: %p (count: %d, intr)\n", intr, count);
     }
@@ -120,12 +120,19 @@
 	msec = INFINITE;
     }
 
-    GVL_UNLOCK_RANGE({
+    GVL_UNLOCK_BEGIN();
+    {
 	DWORD ret;
+	int status = th->status;
+	th->status = THREAD_STOPPED;
+	th->interrupt_function = native_thread_interrupt;
 	thread_debug("native_sleep start (%d)\n", (int)msec);
 	ret = w32_wait_event(0, msec, th);
 	thread_debug("native_sleep done (%d)\n", ret);
-    });
+	th->interrupt_function = 0;
+	th->status = status;
+    }
+    GVL_UNLOCK_END();
 }
 
 int

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2006-05-05 05:07:40 UTC (rev 496)
+++ trunk/yarvcore.h	2006-05-07 12:20:19 UTC (rev 497)
@@ -10,7 +10,7 @@
 
 #include <setjmp.h>
 
-#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
+#if 0 && defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
 #include <ucontext.h>
 #define USE_CONTEXT
 #endif


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]