Dear All, (sorry for the long post) I have been experimenting a bit with GCD in MacRuby 0.5 beta. I have managed to get some code working as I would expect it to work, and I am wondering if a few of you could provide a sanity check that everything i am doing is above board and not the result of unspecified behaviour. My main concern is that when running a set of tasks and collecting the results that the collecting itself is not thread safe (in this case the << operator). And if it is not thread safe - then what is the best way to collect results from dispatched tasks. But so far it seems to work magically well. Before I put the code down - here are some initial discoveries (which may have been obvious to everyone else). 1. When running tests you need wait until the threads are finished - otherwise the main loop will finish before the output comes back from other threads. I did that with a sleep, but also experimented with looping until an array is filled. 2. Scope: Given one of the global system queues : gcdq = Dispatch::Queue.concurrent(:default) and looping over a number of dispatches: 5.times do |index| gcdq.dispatch {puts index} end the task dispatched will hold the last value of index - it will not capture the changing value of index - I assume that the task has a pointer directly to the index variable. (an article by Bill Bumgarner http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/ pointed out something similar in objC - but had a different way of solving this) So to capture that changing index, I created a Proc then turned it back to a block, eg: 5.times do |index| task = Proc.new {puts index} gcdq.dispatch &task end 3. You will notice that in the code below in check = a.run-disp2 that the array is returned - I assume empty - and is gradually filled by the tasks. class A def run_disp(an_array) gcdq = Dispatch::Queue.concurrent(:default) ["f","g","h","i", "j"].each_with_index do |val, index| task = Proc.new {an_array << do_something(val, index)} gcdq.dispatch &task puts "Loaded #{index}" end end def run_disp2 an_array = [] gcdq = Dispatch::Queue.concurrent(:default) ["f","g","h","i", "j"].each_with_index do |val, index| task = Proc.new {an_array << do_something(val, index)} gcdq.dispatch &task puts "Loaded #{index}" end an_array end def do_something(val, index) #staggered sleeps so as to prove that various tasks finish first result = val * (index + 1) case index when 0, 1 sleep 2 when 2 sleep 1 else sleep 0 end puts "yeah baby! #{index}" result end end a = A.new #pass array to be filled an_array = [] a.run_disp(an_array) sleep 10 puts "passed array: #{an_array.join(", ")}" check = a.run_disp2 sleep 10 puts "returned array: #{check.join(", ")}" #results: # Loaded 0 # Loaded 1 # Loaded 2 # Loaded 3 # Loaded 4 # yeah baby! 4yeah baby! 3 # # yeah baby! 2 # yeah baby! 1 # yeah baby! 0 # passed array: iiii, jjjjj, hhh, gg, f # Loaded 0 # Loaded 1 # Loaded 2 # Loaded 3 # Loaded 4 # yeah baby! 3 # yeah baby! 4 # yeah baby! 2 # yeah baby! 0 # yeah baby! 1 # returned array: iiii, jjjjj, hhh, f, gg #assume puts is not transactional. thanks in advance for any comments / corrections, John