Errors with monitor

getting this error in a synchronize call:

/usr/lib/ruby/1.8/monitor.rb:212:in mon_enter': undefined method+’
for nil:NilClass (NoMethodError)
from /usr/lib/ruby/1.8/monitor.rb:236:in `synchronize’

class definition is here:

class SyncPipe < IO
include MonitorMixin

def initialize( p )
@file = IO.popen( p )
end

def puts( output)
synchronize do
@file.puts(output)
end
end

def close
@file.close
end
end

The idea is to have a pipe that threads can write their output too
without interfering with each other…

Any idea what is going wrong. I had this working at one stage, sigh…

Russell

On 10/07/2009 05:28 AM, Russell F. wrote:

include MonitorMixin

def close
@file.close
end
end

The idea is to have a pipe that threads can write their output too
without interfering with each other…

Any idea what is going wrong. I had this working at one stage, sigh…

I believe there are some issues with your code. The one which stroke me
first is that you do not guard #close which can likely result in issues.

Then you inherit IO and leave most methods untouched which also means
they are not guarded. Btw, I don’t believe that you actually need to
inherit class IO.

IIRC IO.popen with just a command name will open only one pipe for
reading stdout so your writing might not succeed anyway.

That’s all not necessarily related to your issue. The show stopper is
that you do not invoke super() in #initialize and thus prevent
initialization of the mixin:

irb(main):021:0> robert@fussel:~$ irb1.8 -r monitor
irb(main):001:0> class X
irb(main):002:1> include MonitorMixin
irb(main):003:1> def foo
irb(main):004:2> synchronize { puts “yy” }
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> X.new.foo
yy
=> nil
irb(main):008:0> class X
irb(main):009:1> def initialize; end # no call to super
irb(main):010:1> end
=> nil
irb(main):011:0> X.new.foo
NoMethodError: undefined method +' for nil:NilClass from /usr/lib/ruby/1.8/monitor.rb:215:inmon_enter’
from /usr/lib/ruby/1.8/monitor.rb:240:in synchronize' from (irb):4:infoo’
from (irb):11
from :0
irb(main):012:0>

Here’s a slightly different approach that takes all these points into
account:

class SyncPipe
include MonitorMixin

def initialize(*a)
super()
@io = IO.popen(*a)
end

def method_missing(*a, &b)
synchronize do
@io.send(*a, &b)
end
end
end

or even more general

class SyncIO
include MonitorMixin

def initialize(io)
super()
@io = io
end

def method_missing(*a, &b)
synchronize do
@io.send(*a, &b)
end
end
end

Kind regards

robert