[MacRuby-devel] [MacRuby] #795: GCD inconsistently copies local variables inside blocks

Rob Gleeson rob at flowof.info
Thu Jul 15 14:56:37 PDT 2010


Oops, by the way, I just meant passing variables that would be written to. It'd require the user to be explicit about what variables they are going to write to, though.

Rob
----
http://robgleeson.github.com	Website
http://github.com/robgleeson   GitHub
rob at flowof.info			        E-Mail


On 15 Jul 2010, at 22:47, Rob Gleeson wrote:

> Hey Ernest,
> 
> Oh okay, and now that code makes more sense :-D
> I'm out of my depth here as I really don't understand GCD nor have I looked into your GCD library. 
> 
> I can only think of one thing, really, and that is to make "i" available as a block parameter.
> The variable would then be block-local, but you would still enjoy the benefits of closures.
> 
> As I understand it, you don't want any mutations to "i" to exist outside the thread you're executing. 
> My 2 cents. Sorry if it is not useful to you.
> 
> Rob
> ----
> http://robgleeson.github.com	Website
> http://github.com/robgleeson   GitHub
> rob at flowof.info			        E-Mail
> 
> 
> On 15 Jul 2010, at 22:38, Ernest N. Prabhakar, Ph.D. wrote:
> 
>> Hi Rob,
>> 
>> On Jul 15, 2010, at 2:34 PM, Rob Gleeson wrote:
>>> Hey again,
>>> 
>>> Sorry just had another idea - since it seems like you don't want the enclosing scope/context to be evaluated in a thread, you could try using instance_eval in a "blank" context where you won't have surrounding variables available to your block.
>>> 
>>> That, and passing arguments to the block as parameters should work but I'm way out of my depth as far as GCD goes.
>> 
>> 
>> Um, I don't think I'm following you.
>> 
>> The real issue with GCD is that it expects blocks to be closures, which capture their local environment.  For the most part, we can pass Ruby blocks and it will "do the right thing" -- but with one caveat.
>> 
>> Ruby allows read-write access to captured variables, but GCD can't, because the block may be executed asynchronously long after the current scope is destroyed.  Therefore, we hack the Ruby runtime to 'const-ify' any local variables that are present in a GCD block.
>> 
>> We don't want to remove -any- reference to local variables, as that would defeat the benefit of using closures.
>> 
>> -- Ernie P.
>> 
>>> 
>>> Rob
>>> ----
>>> http://robgleeson.github.com	Website
>>> http://github.com/robgleeson   GitHub
>>> rob at flowof.info			        E-Mail
>>> 
>>> 
>>> On 15 Jul 2010, at 22:29, Rob Gleeson wrote:
>>> 
>>>> Hey ernest,
>>>> 
>>>> I haven't got any experience with GCD but wouldn't it make more sense if block arguments were received as parameters to the block?
>>>> This would make the variables block-local.
>>>> 
>>>> Dispatch::Queue.new("i").sync { |i| # block local 'i' }
>>>> 
>>>> Remember blocks in Ruby are closures, too. 
>>>> 
>>>> Rob
>>>> ----
>>>> http://robgleeson.github.com	Website
>>>> http://github.com/robgleeson   GitHub
>>>> rob at flowof.info			        E-Mail
>>>> 
>>>> 
>>>> On 15 Jul 2010, at 21:47, MacRuby wrote:
>>>> 
>>>>> #795: GCD inconsistently copies local variables inside blocks
>>>>> ----------------------------------------+-----------------------------------
>>>>> Reporter:  ernest.prabhakar@…          |       Owner:  lsansonetti@…        
>>>>> Type:  defect                      |      Status:  new                  
>>>>> Priority:  critical                    |   Milestone:                       
>>>>> Component:  MacRuby                     |    Keywords:                       
>>>>> ----------------------------------------+-----------------------------------
>>>>> The expectation is that Ruby blocks will have their local variables copied
>>>>> before being passed to GCD, to avoid errors from accessing them after they
>>>>> are destroyed.
>>>>> 
>>>>> However, that does not seem to always happen.  For example:
>>>>> 
>>>>> $ macruby -e 'i=0; Dispatch::Queue.new("i").sync {i = 42}; puts i'
>>>>> 
>>>>> returns '0' as expected.  However, this does not:
>>>>> 
>>>>> $ macirb
>>>>> irb(main):001:0> i=0; Dispatch::Queue.new("i").sync {i = 42}; puts i
>>>>> 42
>>>>> => nil
>>>>> 
>>>>> It appears to be copied properly in the block_spec.rb test:
>>>>> 
>>>>> it "should create const copies of dynamic (local) variables" do
>>>>>   i = 42
>>>>>   @q.sync {i = 1}
>>>>>   i.should == 42
>>>>> end
>>>>> 
>>>>> But not in the README.rdoc for the dispatch module (aka
>>>>> dispatch_methods.rb sample):
>>>>> 
>>>>> n = 0
>>>>> job = Dispatch::Job.new { n = 21 }
>>>>> job.join
>>>>> puts "n (after): #{n} => 0?!?" # [returns 21, not 0]
>>>>> 
>>>>> Any suggestions?
>>>>> 
>>>>> -- 
>>>>> Ticket URL: <http://www.macruby.org/trac/ticket/795>
>>>>> MacRuby <http://macruby.org/>
>>>>> 
>>>>> _______________________________________________
>>>>> MacRuby-devel mailing list
>>>>> MacRuby-devel at lists.macosforge.org
>>>>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>>>> 
>>>> _______________________________________________
>>>> MacRuby-devel mailing list
>>>> MacRuby-devel at lists.macosforge.org
>>>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>>> 
>>> _______________________________________________
>>> MacRuby-devel mailing list
>>> MacRuby-devel at lists.macosforge.org
>>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>> 
>> _______________________________________________
>> MacRuby-devel mailing list
>> MacRuby-devel at lists.macosforge.org
>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
> 
> _______________________________________________
> MacRuby-devel mailing list
> MacRuby-devel at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel



More information about the MacRuby-devel mailing list