Mark Hubbart
2/11/2005 11:02:00 PM
Hi,
On Fri, 11 Feb 2005 13:25:05 +0900, Yukihiro Matsumoto
<matz@ruby-lang.org> wrote:
> Hi,
>
> In message "Re: "stack level too deep"... because Threads keep their "starting" stack"
> on Fri, 11 Feb 2005 13:19:53 +0900, Sam Roberts <sroberts@uniserve.com> writes:
>
> |Is there any way to strip your calling context, or does it break the
> |language somehow? Is it needed for purposes other than debugging?
>
> No way to strip. It's a limitation of the current thread
> implementation.
This might work. This is only lightly tested, so there might be hidden
bugs, or issues I didn't think of. And it's not exactly the prettiest
code :) Just a quick POC.
## unstacker.rb
require 'thread'
class Thread
THREADS_TO_CREATE = []
THREAD_CREATION_MUTEX = Mutex.new
class ThreadUnstacker < Thread
alias_method :kill!, :kill
def kill() false end
end
UNSTACKER = ThreadUnstacker.new do
loop do
sleep
request = THREADS_TO_CREATE.shift
request[:thread] = Thread.new &request[:proc]
request[:requester].wakeup
end
end
def self.unstack(&block)
request = {}
request[:proc] = block
request[:requester] = Thread.current
THREAD_CREATION_MUTEX.synchronize do
THREADS_TO_CREATE << request
UNSTACKER.wakeup
sleep until request[:thread]
end # sync
request[:thread]
end
end
## irb session:
irb> def recurse(times, &block)
irb> times.zero?? block.call : recurse(times-1, &block)
irb> end
==>nil
irb> recurse(2000){Thread.new{puts "caller.size: #{caller.size}"}}
caller.size: 2008
==>#<Thread:0x579644 dead>
irb> recurse(2000){Thread.unstack{puts "caller.size: #{caller.size}"}}
caller.size: 12
==>#<Thread:0x5a3278 dead>
cheers,
Mark