Synchronized object

Dear ruby-talk,

is there a nice, concise way to lock each and
every method against all other methods of an object?

To elaborate: I want to make sure that only one method of
a specific object (not class) can run at a each point in
time regardless of how many threads are using this object.

I would hope there is module i just have to include in
my class definition.

cheers and thanks

Simon

You could have a class wide Mutex.

class MyClass
  @@mutex = Mutex.new
  def atomicy_method
    @@mutex.synchronise do
        # Code here
    end
  end
end

Farrel

Simon,

Look at the Monitor module.

For example:
require 'monitor'

class Foo
  include MonitorMixin

  def bar
    self.synchronized do
      # stuff
    end
  end

  def baz
    self.synchronized do
      # more stuff
    end
  end
end

It's a little less syntactically sugary than Java, but about the same as C#.

Do this help?

Thanks,

David

···

On 4/21/06, Kroeger, Simon (ext) <simon.kroeger.ext@siemens.com> wrote:

Dear ruby-talk,

is there a nice, concise way to lock each and
every method against all other methods of an object?

To elaborate: I want to make sure that only one method of
a specific object (not class) can run at a each point in
time regardless of how many threads are using this object.

I would hope there is module i just have to include in
my class definition.

cheers and thanks

Simon

You could wrap it in a delegate object you strip of methods, then just have method_missing() forward the messages inside a synchronize block.

James Edward Gray II

···

On Apr 21, 2006, at 9:47 AM, Kroeger, Simon (ext) wrote:

Dear ruby-talk,

is there a nice, concise way to lock each and
every method against all other methods of an object?

To elaborate: I want to make sure that only one method of
a specific object (not class) can run at a each point in
time regardless of how many threads are using this object.

I would hope there is module i just have to include in
my class definition.

Well it's not quite as easy as Java but:
http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/index.html

obj.methods.each do |meth|
    (class << obj; self; end).module_eval <<HERE
       def #{meth}(*args, &block)
           self.synchronize { super }
       end
HERE

end

obj.extend(MonitorMixin)

I did it in that order since I wouldn't want a synchronize { synchronize }

···

On Apr 21, 2006, at 10:47 AM, Kroeger, Simon (ext) wrote:

Dear ruby-talk,

is there a nice, concise way to lock each and
every method against all other methods of an object?

To elaborate: I want to make sure that only one method of
a specific object (not class) can run at a each point in
time regardless of how many threads are using this object.

I would hope there is module i just have to include in
my class definition.

cheers and thanks

Simon

If you want something like you get in Java with the "synchronized"
keyword, that's a monitor, and the standard library includes
(the not terribly well documented) monitor.rb:

http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/

(also Monitor (synchronization) - Wikipedia )

Whether it's nice or concise I don't know - it's certainly not a
"one-liner" way to achieve what you want but it might get you a long
way along the road. If you use it, I'd personally be interested in
how you got on.

(Caveat: I haven't used this, I just saw "synchronized object" in your
subject line, thought "monitor", and searched the web for "ruby
monitor synchronization" which led me to this info.)

Hope this helps,

-Andy

···

On Fri, Apr 21, 2006 at 11:47:56PM +0900, Kroeger, Simon (ext) wrote:

Dear ruby-talk,

is there a nice, concise way to lock each and every method against
all other methods of an object?

To elaborate: I want to make sure that only one method of a specific
object (not class) can run at a each point in time regardless of how
many threads are using this object.

I would hope there is module i just have to include in my class
definition.

--
Andy Gimblett
Computer Science Department
University of Wales Swansea
http://www.cs.swan.ac.uk/~csandy/

It would be relatively easy to write a class that uses Monitor and delegates
to specifc object. Thus, much like Java's Collections.synchronizedFoo, you
could have

Synchronizer.new(foo) that would synchronize ANY object.

David

···

On Friday 21 April 2006 10:47 am, Kroeger, Simon (ext) wrote:

Dear ruby-talk,

is there a nice, concise way to lock each and
every method against all other methods of an object?

To elaborate: I want to make sure that only one method of
a specific object (not class) can run at a each point in
time regardless of how many threads are using this object.

I would hope there is module i just have to include in
my class definition.

cheers and thanks

Simon

Logan Capaldo wrote:

Well it's not quite as easy as Java but:
http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/index.html

obj.methods.each do |meth|
   (class << obj; self; end).module_eval <<HERE
      def #{meth}(*args, &block)
          self.synchronize { super }
      end
HERE

end

obj.extend(MonitorMixin)

I did it in that order since I wouldn't want a synchronize { synchronize }

accepted answer ... well kind of. :wink:

running your code (with an empty array) gave me:

ruby 1.8.4 (2005-12-24) [i386-mswin32]

(eval):1: warning: redefining `__send__' may cause serious problem
(eval):1: warning: redefining `__id__' may cause serious problem
(eval):2:in `extend': undefined method `synchronize' for
#<Array:0x2816468> (NoMethodError)

but i got the right idea i think. My code now looks like:

···

---------------------------------------------------------------------
require 'monitor'

def sync obj
  meth = obj.methods - %w{__send__ __id__}
  klass = class << obj.extend(MonitorMixin); self; end
  meth.each{|m|klass.module_eval "def #{m}(*a,&b)synchronize{super}end"}
  obj
end

---------------------------------------------------------------------

usage:
---------------------------------------------------------------------
obj = sync()
obj.push 'a'
p obj
---------------------------------------------------------------------

and now that i see it, it looks quite simple :slight_smile:

thanks to all of you who responded

cheers

Simon

require 'monitor'

class AutoMonitor
  include MonitorMixin

  def initialize(obj)
    mon_initialize
    @obj = obj
  end

  def method_missing(sym, *args, &block)
    synchronize do
      @obj.send(sym, *args, &block)
    end
  end
end

class Class
  def monitored_new(*args, &block)
    AutoMonitor.new(new(*args, &block))
  end
end

Something like this and then you can:

f = Foo.monitored_new

pth

···

On 4/21/06, David Corbin <dcorbin@machturtle.com> wrote:

On Friday 21 April 2006 10:47 am, Kroeger, Simon (ext) wrote:
> Dear ruby-talk,
>
> is there a nice, concise way to lock each and
> every method against all other methods of an object?
>
> To elaborate: I want to make sure that only one method of
> a specific object (not class) can run at a each point in
> time regardless of how many threads are using this object.

> I would hope there is module i just have to include in
> my class definition.
>
> cheers and thanks
>
> Simon

It would be relatively easy to write a class that uses Monitor and delegates
to specifc object. Thus, much like Java's Collections.synchronizedFoo, you
could have

Synchronizer.new(foo) that would synchronize ANY object.

David

Thanks a lot, but consider this:

···

-------------------------------------------------------------------------
require 'monitor'

class AutoMonitor
  include MonitorMixin

  def initialize(obj)
    mon_initialize
    @obj = obj
  end

  def method_missing(sym, *args, &block)
    synchronize do
      @obj.send(sym, *args, &block)
    end
  end
end

def sync obj
  meth = obj.methods - %w{__send__ __id__}
  klass = class << obj.extend(MonitorMixin); self; end
  meth.each{|m|klass.module_eval "def #{m}(*a,&b)synchronize{super}end"}
  obj
end

hash = {"test1" => 1, AutoMonitor.new("test2") => 2, sync('test3') => 3}

p hash.include?("test1") #=> true
p hash.include?(AutoMonitor.new("test1")) #=> false
p hash.include?("test2") #=> false
p hash.include?(AutoMonitor.new("test2")) #=> false

#but

p hash.include?("test1") #=> true
p hash.include?(sync("test1")) #=> true
p hash.include?("test3") #=> true
p hash.include?(sync("test3")) #=> true
-------------------------------------------------------------------------

Of course it is possible to enhance AutoMonitor to handle these cases,
but i like the 4 liner. :slight_smile:

If only i could make this module_eval go away. (or at least use the
block form)

cheers

Simon

Patrick Hurley wrote:

On 4/21/06, David Corbin <dcorbin@machturtle.com> wrote:
[...]
require 'monitor'

class AutoMonitor
  include MonitorMixin

  def initialize(obj)
    mon_initialize
    @obj = obj
  end

  def method_missing(sym, *args, &block)
    synchronize do
      @obj.send(sym, *args, &block)
    end
  end
end

class Class
  def monitored_new(*args, &block)
    AutoMonitor.new(new(*args, &block))
  end
end

Something like this and then you can:

f = Foo.monitored_new

pth