From: Mark Hubbart Date: 2005-02-12T08:02:29+09:00 Subject: Re: "stack level too deep"... because Threads keep their "starting" stack Hi, On Fri, 11 Feb 2005 13:25:05 +0900, Yukihiro Matsumoto 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 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 ==># irb> recurse(2000){Thread.unstack{puts "caller.size: #{caller.size}"}} caller.size: 12 ==># cheers, Mark