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. 
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 
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. 
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