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 Apr 21, 2006, at 9:47 AM, Kroeger, Simon (ext) wrote:
my class definition.
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 G. II
On Apr 21, 2006, at 10:47 AM, Kroeger, Simon (ext) wrote:
my class definition.
cheers and thanks
Simon
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 }
Logan C. wrote:
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
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
On Fri, Apr 21, 2006 at 11:47:56PM +0900, Kroeger, Simon (ext) wrote:
definition.
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
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
On 4/21/06, David C. [email protected] wrote:
I would hope there is module i just have to include in
Synchronizer.new(foo) that would synchronize ANY object.
David
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