How to overload Object's methods automagicaly?

S

S.Z.

I am playing with a Synchronized class that automates resource locking
(code snippet can be found here:
http://www.rubygarden.org/ruby?MultiThreading).
One issue arised is how to overload all (or particular) Object's (or
some ancestor's) methods by the automated way?
Syncronized extraction looks like this:

class Syncronized
def initialize( klass, *args )
@obj= klass::new( *args );
end

def to_s() @obj.to_s(); end
# What about clone(), taint(), and other?
end

It is hard work to type all the Objecs's methods by hand in spite of
their bodies are the same.
What is the better choice?
 
R

Ralf Müller

I am playing with a Synchronized class that automates resource locking
(code snippet can be found here:
http://www.rubygarden.org/ruby?MultiThreading).
One issue arised is how to overload all (or particular) Object's (or
some ancestor's) methods by the automated way?
Syncronized extraction looks like this:

class Syncronized
def initialize( klass, *args )
@obj= klass::new( *args );
end

def to_s() @obj.to_s(); end
# What about clone(), taint(), and other?
end

It is hard work to type all the Objecs's methods by hand in spite of
their bodies are the same.
What is the better choice?

What about the "methods" method? You get an Array whith all the method-names of the current object.
Maybe something like this

class Sync
def initialze (klass, *args)
@object = klass::new(*args)
@object.methods.each do |m|
def m(a)
object.m(a)
end
end
end

I know, this won't run - just an idea.


--
 
R

Robert Klemme

S.Z. said:
I am playing with a Synchronized class that automates resource locking
(code snippet can be found here:
http://www.rubygarden.org/ruby?MultiThreading).
One issue arised is how to overload all (or particular) Object's (or
some ancestor's) methods by the automated way?
Syncronized extraction looks like this:

class Syncronized
def initialize( klass, *args )
@obj= klass::new( *args );
end

def to_s() @obj.to_s(); end
# What about clone(), taint(), and other?
end

It is hard work to type all the Objecs's methods by hand in spite of
their bodies are the same.
What is the better choice?

You can iterate all instance methods, alias each one and create a new one
calling the original one synchronized. Delegate might be helpful, too.

Note though that automatically synchronizaton of each method is not
necessarily going to make your program thread safe. Every transaction
that involves more than one method invocation won't be thread safe with
this approach - in this case you need explicit external synchronization:

# typical example
unless hash.contains_key? "foo"
# lengthy calculation
hash["foo"] = result_of_lenthy_calculation
end

Other typical examples involve scenarios where several instances have to
be changed consistently. All these are reasons why Sun stepped away from
full synchronization (Vector, StringBuffer) and added classes that do not
employ method level synchronization (ArrayList, StringBuilder), which is
more performant.

Kind regards

robert
 
S

S.Z.

Robert said:
You can iterate all instance methods, alias each one and create a new one
calling the original one synchronized. Delegate might be helpful, too.
Eurica!
I need not to define, but rather to undefine the Object's methods:
undef :to_s, :taint, :clone;
Now method_missing() can operate.
Note though that automatically synchronizaton of each method is not
necessarily going to make your program thread safe. Every transaction
that involves more than one method invocation won't be thread safe with
this approach - in this case you need explicit external synchronization
Any transaction on an object can be treated as a single method call.
Transaction's body can be known only at runtime; but it is not a
problem in Ruby.
Sun stepped away from
full synchronization (Vector, StringBuffer) and added classes that do not
employ method level synchronization (ArrayList, StringBuilder), which is
more performant.
This approach is erroprone, I think...

-- many thanks
 
R

Robert Klemme

S.Z. said:
Eurica!
I need not to define, but rather to undefine the Object's methods:
undef :to_s, :taint, :clone;
Now method_missing() can operate.

And which method do you invoke then if you undefined all those methods?
Any transaction on an object can be treated as a single method call.

Certainly not! It might in a many scenarios but there's also a lot
scenarios where this does not apply. This statement as a general
statement is wrong.
Transaction's body can be known only at runtime; but it is not a
problem in Ruby.

What are you trying to say here?
This approach is erroprone, I think...

Not at all. It's exactly the way to go. Built in sychronization of every
method is pointless because you never get the class without
synchronization overhead. This can have serious impact on applications as
every synchronized necessitates synchronization of thread local memory
(there are some nice articles on the web on how Java VM handles
concurrency, synchronization - look for "JVM memory model").

Honestly, I'm not sure that you completely grokked concurrency. I suggest
you get yourself a copy of "Concurrent Programming in Java" if you want to
dig deeper into the matter

http://www.amazon.com/exec/obidos/tg/detail/-/0201310090

Kind regards

robert
 
S

S.Z.

Robert said:
And which method do you invoke then if you undefined all those methods?
If I invoke to_s() on Sync object, then method_missing() will be
called because to_s() has been undefined for Sync class.
method_missing() can do all I want to be done.

Robert said:
Certainly not! It might in a many scenarios but there's also a lot
scenarios where this does not apply. This statement as a general
statement is wrong.
Would you show an example in which this does not apply?

Robert said:
What are you trying to say here?
Excuse my poor English.
Transaction is not a method call, rather a context for several method
calls.
But, if we can put these calls to single batch and invoke it then
transacton is just a method call, except for begin/commit semantics.
In Ruby we can easily create such a batch.

Robert said:
Built in sychronization of every
method is pointless because you never get the class without
synchronization overhead.
It is obvious.
Rather having an ordinary object I need to construct the synchronized
one without the use of errorprone external mutexes and randevous.
As the first step, I have created Sync class to hold the object and the
sync semantics.
In the simplest case of read/write unordered buffer only per-method
synchronization is needed and therefore Sync class can solve the task.

-- many thanks twice
 
R

Robert Klemme

S.Z. said:
If I invoke to_s() on Sync object, then method_missing() will be
called because to_s() has been undefined for Sync class.
method_missing() can do all I want to be done.

Well yes, but from what I understand from your postings your aim is to
make each method synchronized automatically. Or are you saying that you
want to use a delegate pattern where method_missing is used to call the
original instance's method synchronized?
Would you show an example in which this does not apply?

I did already. Every scenario where at least two method calls on the same
or multiple objects have to be atomic with regard to other threads'
activities.
Excuse my poor English.
Transaction is not a method call, rather a context for several method
calls.
But, if we can put these calls to single batch and invoke it then
transacton is just a method call, except for begin/commit semantics.
In Ruby we can easily create such a batch.

You have that feature already with Mutex#synchronized and
Monitor#synchronized. There's also a variant as mixin (see doc ref
below).
It is obvious.
Rather having an ordinary object I need to construct the synchronized
one without the use of errorprone external mutexes and randevous.

So you're using Java's delegation approach with
Collection.synchronizedList() etc., i.e. you have a wrapper class that
does the synchronization and then delegates each method call to the real
object.
As the first step, I have created Sync class to hold the object and
the sync semantics.

You don't need to create that on your own. It's already there:
http://www.ruby-doc.org/stdlib/libdoc/thread/rdoc/index.html
http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/index.html
In the simplest case of read/write unordered buffer only per-method
synchronization is needed and therefore Sync class can solve the task.

Yes, but only in these cases.

Regards

robert
 
S

S.Z.

Robert said:
from what I understand from your postings your aim is to
make each method synchronized automatically. Or are you saying that you
want to use a delegate pattern where method_missing is used to call the
original instance's method synchronized?
I want to use method_missing() to call the original methods
synchronized.
I did already. Every scenario where at least two method calls on the same
or multiple objects have to be atomic with regard to other threads'
activities.
Below you have mentioned Monitor#synchronized(), that is just a
contradiction.
You have that feature already with Mutex#synchronized and
Monitor#synchronized. There's also a variant as mixin (see doc ref
below).
Yes I have. But I dislike both. I know a better solution only for
scenarios where my Sync class can be applied. But I am looking for the
others...
So you're using Java's delegation approach
Yes, I do the same with Ruby.
You don't need to create that on your own. It's already there
Look at MonitorMixin example:
http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/classes/MonitorMixin.html
Is not this an errorprone code? I need a better sync mechanism that
defines "producer" and "consumer" and has the correct zyncronization
built in.
 
R

Robert Klemme

S.Z. said:
Robert Klemme wrote:
Below you have mentioned Monitor#synchronized(), that is just a
contradiction.

Where is this a contradiction?
Yes I have. But I dislike both. I know a better solution only for
scenarios where my Sync class can be applied. But I am looking for the
others...

What's your problem with these? Why do you dislike them? Why can't you
use them to implement your Sync class?
Yes, I do the same with Ruby.

Look at MonitorMixin example:
http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/classes/MonitorMixin.html
Is not this an errorprone code? I need a better sync mechanism that
defines "producer" and "consumer" and has the correct zyncronization
built in.

If you're in a producer consumer scenario use a Queue.
http://www.ruby-doc.org/stdlib/libdoc/thread/rdoc/classes/Queue.html

Seriously, I really don't know why you think you have to cook something
completely new while there is lots of stuff that seems to be doing what
you need. Maybe it's just a language issue but I have the feeling that
you always write at most half of what you think. That makes it really
hard to follow this thread.

Cheers

robert
 
A

Ara.T.Howard

On Thu, 13 Oct 2005, Robert Klemme wrote:

Maybe it's just a language issue but I have the feeling that you always
write at most half of what you think.


i only think at most half of what i write. is that bad? ;-)

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
B

Brock Weaver

------=_Part_3122_1165766.1129218136175
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

"We were given two ears and one mouth so we speak only half of what we
hear".

...and yet we get two hands to type with. Darn technology.

I'd guess a 1:2 ratio of think:write is higher than most people's
threshhold. It obviously is higher than mine. :)

On Thu, 13 Oct 2005, Robert Klemme wrote:

Maybe it's just a language issue but I have the feeling that you always
write at most half of what you think.


i only think at most half of what i write. is that bad? ;-)

-a
--

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D


--
Brock Weaver
(e-mail address removed)

/* you are not expected to understand this */

------=_Part_3122_1165766.1129218136175--
 
S

S.Z.

Robert said:
Where is this a contradiction?
When MonitorMixin is used any transaction can be treated as single
method call (syncronize() with the block as parameter).
Why can't you use them to implement your Sync class?
I did it with the Mutex. These are the nice lowlevel mechanics, but
using it is erroprone (as it is with any lowlevel mechanic).
If you're in a producer consumer scenario use a Queue.
Oh no, please, no!
The writer must start to write only if the reader has already started
to read (otherwise data may be lost). I want a better mechanism: 1)
create obj1 and obj2; 2) assign "writer" role to the obj1 and "reader"
to the obj2; 3) create a Queue then attach obj1 and obj2 to it; 4) run
the collaboration.
What I need are more higher level Concurrent Programming Pattens
implemented in Ruby. Using Mutexes to implement these is tedious. I
want more higher level mechanics. A thread need not to wory about
whether it is alone or not, so non-concurrent code can be easily
converted to concurrent one and vise versa.
Seriously, I really don't know why you think you have to cook something
completely new while there is lots of stuff that seems to be doing what
you need.
Because the stuff is not exactly what I need. What I need is a long
story though...
Maybe it's just a language issue but I have the feeling that
you always write at most half of what you think.
I have enough words, but have not enough time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top