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