Adding stack helper methods (Old)
rscottm edited this page Oct 8, 2011
·
1 revision
# Options:
# :stack_size
# :when_done - block performed on the calling thread
# :when_failed - block performed on the calling thread
# :wait - wait for the block to complete
def do_in_thread(args = {}, &block)
handler = Java::android.os.Handler.new if args[:when_done] or args[:when_failed]
thread_proc = Proc.new do
begin
block.call
handler.post(args[:when_done]) if args[:when_done]
rescue
handler.post(args[:when_failed]) if args[:when_failed]
end
end
if args[:stack_size]
t = java.lang.Thread.new(nil, thread_proc, nil, args[:stack_size])
else
t = java.lang.Thread.new(nil, thread_proc)
end
t.join if args[:wait]
t
end
Usage
# Run some code with large stack and get the result
result1 = nil
do_in_thread(:wait => true){result1 = some_library_call}
do_in_thread{result1 = some_library_call}.join
# Run some code with large stack and get the result. Specify stack size.
result2 = nil
with_large_stack(256){result2 = some_other_library_call}
do_in_thread(:stack_size => 256, :wait => true){result2 = some_other_library_call}
do_in_thread(:stack_size => 256){result1 = some_library_call}.join
# Run some code in the background with large stack
result3 = nil
do_in_thread(:stack_size => 256) do
stuff_requiring_large_stack
result3 = 42
end
# Run some code in the background with large stack then update the calling thread with the result.
result4 = nil
do_in_thread(:stack_size => 256, :when_done => proc{result4 = 42}) do
stuff_requiring_large_stack
end
# Run some code in the background with large stack then update the calling thread with the result, including exceptions.
status_view = text_view
do_in_thread(:stack_size => 256, :when_done => proc{status_view.text = 'SUCCESS'}, :when_failed => proc{status_view.text = 'FAILED'}) do
stuff_requiring_large_stack
end
# Run some code with large stack and get the result
result1 = nil
do_in_thread(:wait => true){result1 = some_library_call}
do_in_thread{result1 = some_library_call}.join
# Run some code with large stack and get the result. Specify stack size.
result2 = nil
with_large_stack(256){result2 = some_other_library_call}
do_in_thread(:stack_size => 256, :wait => true){result2 = some_other_library_call}
do_in_thread(:stack_size => 256){result1 = some_library_call}.join
# Run some code in the background with large stack
result3 = nil
do_in_thread(:stack_size => 256) do
stuff_requiring_large_stack
result3 = 42
end
# Run some code in the background with large stack then update the calling thread with the result.
result4 = nil
do_in_thread(:stack_size => 256, :when_done => proc{result4 = 42}) do
stuff_requiring_large_stack
end
# Run some code in the background with large stack then update the calling thread with the result, including exceptions.
status_view = text_view
do_in_thread(:stack_size => 256, :when_done => proc{status_view.text = 'SUCCESS'}, :when_failed => proc{status_view.text = 'FAILED'}) do
stuff_requiring_large_stack
end
Idea two
class Object
def with_large_stack(stack_size_kb = 64, &block)
result = nil
t = Thread.with_large_stack(&proc{result = block.call})
t.join
result
end
end
class Thread
def self.with_large_stack(stack_size_kb = 128, &block)
t = java.lang.Thread.new(nil, block, "block with large stack", stack_size_kb * 1024)
t.start
t
end
end
class Object
def with_large_stack(stack_size_kb = 64, &block)
result = nil
t = Thread.with_large_stack(&proc{result = block.call})
t.join
result
end
end
class Thread
def self.with_large_stack(stack_size_kb = 128, &block)
t = java.lang.Thread.new(nil, block, "block with large stack", stack_size_kb * 1024)
t.start
t
end
end
# Run some code with large stack and get the result
result1 = with_large_stack{some_library_call}
# Run some code with large stack and get the result. Specify stack size.
result2 = with_large_stack(256){some_other_library_call}
# Run some code in the background
Thread.start do
stuff_run_in_the_background
end
# Run some code in the background with large stack
Thread.with_large_stack do
stuff_requiring_large_stack
end
# Run some code in the background with large stack specifying stack size
Thread.with_large_stack(128) do
stuff_requiring_large_stack
end
# Run some code in the background with large stack then update the calling thread with the result.
result3 = nil
Thread.with_large_stack do
stuff_requiring_large_stack
run_on_ui_thread{result3 = 42}
end
# Run some code in the background with large stack then update the calling thread with the result, including exceptions.
status_view = text_view
Thread.with_large_stack(256) do
begin
stuff_requiring_large_stack
run_on_ui_thread{status_view.text = 'SUCCESS'}
rescue
run_on_ui_thread{status_view.text = 'FAILED'}
end
end
Over designed hybrid. Assumes two main use cases: 1) execute code in another thread, and 2) execute code needing large stack. Don’t need all of these calls. Could just select a subset.
class Object
def eval_with_large_stack(str, stack_size_kb = 128)
call_in_thread(stack_size_kb, &proc{eval(str)})
end
def eval_in_thread(str, stack_size_kb = 16)
call_in_thread(stack_size_kb, &proc{eval(str)})
end
def call_with_large_stack(stack_size_kb = 128, &block)
call_in_thread(stack_size_kb, &block)
end
def call_in_thread(stack_size_kb = 16, &block)
result = nil
java.lang.Thread.call(stack_size_kb, &proc{result = block.call}).join
result
end
end
class Proc
def call_in_thread(stack_size_kb = 16)
java.lang.Thread.call(stack_size_kb, &self)
end
def call_with_large_stack(stack_size_kb = 128)
call_in_thread(stack_size_kb, &self)
end
end
java.lang.Thread.class_eval do
def self.eval(str, stack_size_kb = 16)
call(stack_size_kb, &proc{eval(str)})
end
def self.call(stack_size_kb = 16, &block)
t = java.lang.Thread.new(nil, block, "block with stack #{stack_size_kb}", stack_size_kb * 1024)
t.uncaught_exception_handler = proc{|t, ex|}
t.start
t
end
end
# Run code in another thread
proc{code_to_not_block_on}.call_in_thread
# or
Thread.call{code_to_not_block_on}
# or (blocks)
result = call_in_thread{code_to_block_on}
# Run some code with large stack and get the result
result1 = call_with_large_stack{some_library_call}
# Run some code with large stack and get the result. Specify stack size.
result2 = call_with_large_stack(256){some_other_library_call}
# Run some code in the background with large stack
proc{stuff_requiring_large_stack}.call_with_large_stack
# Run some code in the background with large stack then update the calling thread with the result.
p = proc do
stuff_requiring_large_stack
run_on_ui_thread{toast("result = 42")}
end
p.call_with_large_stack
# Run some code in the background with large stack then update the calling thread with the result, including exceptions.
status_view = text_view
p = proc do
begin
stuff_requiring_large_stack
run_on_ui_thread{status_view.text = 'SUCCESS'}
rescue
run_on_ui_thread{status_view.text = 'FAILED'}
end
end
p.call_with_large_stack(256)