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