[MacRuby] #1393: Invocation of blocks registered using -[NSNotificationCenter addObserverForName:object:queue:usingBlock:] is unreliable
MacRuby
ruby-noreply at macosforge.org
Thu Sep 29 08:59:30 PDT 2011
#1393: Invocation of blocks registered using -[NSNotificationCenter
addObserverForName:object:queue:usingBlock:] is unreliable
--------------------------------+-------------------------------------------
Reporter: sohocoke@… | Owner: lsansonetti@…
Type: defect | Status: new
Priority: blocker | Milestone:
Component: MacRuby | Keywords:
--------------------------------+-------------------------------------------
It seems that when a block / proc is registered for notification (cf. a
selector), its invocation occasionally fails.
Here is a program that, occasionally, reproduces the case.
notification-test.rb
{{{
# reduced case of block-based observation
framework 'cocoa'
require 'thread'
class TestSender
def send
NSNotificationCenter.defaultCenter.postNotification
NSNotification.notificationWithName(:kTestNotification, object:[1, 2, 3])
end
end
class ObjectWithCounter
attr_reader :counter
def initialize
super
@counter = 0
@mutex = Mutex.new
end
def increment
@mutex.synchronize {
@counter += 1
}
end
end
class Observer1 < ObjectWithCounter
def listen_with_block
NSNotificationCenter.defaultCenter.addObserverForName
:kTestNotification, object:nil, queue:nil, usingBlock:Proc.new {
|notification|
NSLog("#{self} notified - in block now.")
self.increment
}
end
end
class Observer2 < ObjectWithCounter
def listen_with_callback
NSNotificationCenter.defaultCenter.addObserver self,
selector:"handle_notification:", name: :kTestNotification, object:nil
end
def handle_notification(notification)
NSLog("#{self} notified of #{notification} - in handler now.")
self.increment
end
end
mutex = Mutex.new
o1_counter, o2_counter = 0, 0
30.times do
sender = TestSender.new
o1 = Observer1.new
o1.listen_with_block
sender.send
o2 = Observer2.new
o2.listen_with_callback
sender.send
mutex.synchronize do
o1_counter += o1.counter
o2_counter += o2.counter
end
end
puts "o1 notified #{o1_counter} times."
puts "o2 notified #{o2_counter} times."
# expect to have o1 notified 60 times, o2 30 times.
}}}
I ran it thusly and observed the output:
{{{
[~/dev/src/mac/macruby]$ while [ 0 ]; do
ruby notification-test.rb >> notification-test.out
done
[~/dev/src/mac/macruby]$ grep 'notified' notification-test.out
o1 notified 60 times.
o2 notified 30 times.
o1 notified 59 times.
o2 notified 30 times.
o1 notified 59 times.
o2 notified 30 times.
o1 notified 58 times.
o2 notified 30 times.
}}}
i (hastily) threw in some mutexes after a first version of the test
program on paranoia of there being a silly threading mistake, but
documentation for the method on NSNotificationCenter suggests that the
erroneous invocation should occur synchronously on the main thread of the
program anyway.
I tried macruby-0.10 and macruby-nightly installed via rvm.
--
Ticket URL: <http://www.macruby.org/trac/ticket/1393>
MacRuby <http://macruby.org/>
More information about the macruby-tickets
mailing list