Ah, indeed, there are subtle differences with lvars at the top-level in IRB vs
in a method scope. Not sure if I'd consider this a bug or not, but to
illustrate:
>> result = nil
=> nil
>> Dispatch::Queue.concurrent.sync do
>> result = true
>> end
=> nil
>> result
=> true
>> def test
>> result = nil
>> Dispatch::Queue.concurrent.sync do
>> result = true
>> end
>> result
>> end
=> nil
>> test
=> nil
Anyway, we're getting away from the original question. If you replace your
lvars with ivars (s/result/@result/ above), then things will work. Just be
careful of the possibility of concurrency bugs when assigning the same ivar
from multiple queued blocks (and also have a look at the dispatch gem which has
some convenience methods to make this sort of thing easier).
On Saturday, October 22, 2011 at 6:30 AM, Michael Johnston wrote:
> Very strange, your example works for me in irb too. Irb must do something odd
> with locals. Have you tried this outside of irb, though? If you wrap with a
> method def'n in irb, it behaves differently, and the fact that locals are
> copied has been discussed lots on the list. But Laurent (I think) said this
> will likely change, has it already? I'm on 0.10
>
>
>
> $ macirb --noprompt
> def check
> print "can I change a local scalar? "
> maybe = "nope"
> $q.sync do
> maybe = "yep"
> end
> puts maybe
> end
> => nil
> def check_p
> print "can I assign to a pointer? "
> maybe_p = Pointer.new(:id)
> maybe_p.assign "nope"
> $q.sync do
> maybe_p.assign "yep"
> end
> puts maybe_p[0]
> end
> => nil
> def check_w
> print "can I assign to a wrapper attr? "
> maybe = ResultWrapper.new("nope")
> $q.sync do
> maybe.value = "yep"
> end
> puts maybe.value
> end
> => nil
> ResultWrapper = Struct.new(:value)
> => ResultWrapper
> $q= Dispatch::Queue.new('q')
> => q
> check
> can I change a local scalar? nope
> => nil
> # but using a pointer works:
> => nil
> check_p
> can I assign to a pointer? yep
> => nil
> # or a wrapper (but more expensive for tight loops):
> => nil
> check_w
> can I assign to a wrapper attr? yep
> => nil
> $q= Dispatch::Queue.concurrent
> => com.apple.root.default-priority
> # double-checking it isn't different for the parallel queues:
> => nil
> check
> can I change a local scalar? nope
> => nil
> check_p
> can I assign to a pointer? yep
> => nil
> check_w
> can I assign to a wrapper attr? yep
> => nil
>
>
>
>
>
>
>
>
>
> Cheerio,
>
> Michael Johnston
> [email protected] (mailto:[email protected])
>
>
>
>
> On 2011-10-22, at 12:32 AM, Joshua Ballanco wrote:
>
> > On Saturday, October 22, 2011 at 1:35 AM, Michael Johnston wrote:
> > > When I need to get a queue-protected result into a local in code that is
> > > concurrent (so I can't use an ivar) is a pointer the best (only) way to
> > > get the result of a sync block? Assuming I don't want to factor out a
> > > method object.
> > >
> > >
> > > ex:
> > >
> > > result_p = Pointer.new(:id)
> > > some_queue.sync do
> > > result_p.assign(value_protected_by_queue)
> > > end
> > > result = result_p[0]
> > >
> > > it's not very ruby-ish...
> >
> > There's no restriction on not using ivars in block. Indeed, even locals are
> > in scope in a block (and with a #sync dispatched block such as the one you
> > provided, there aren't even any threading issues):
> >
> > result = nil
> > Dispatch::Queue.concurrent.sync do
> > result = true
> > end
> > p result #=> true
> > _______________________________________________
> > MacRuby-devel mailing list
> > [email protected]
> > (mailto:[email protected])
> > http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>
> _______________________________________________
> MacRuby-devel mailing list
> [email protected] (mailto:[email protected])
> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________
MacRuby-devel mailing list
[email protected]
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel