[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How to duplicate a object changing the class without attributes memory copy

Iñaki Baz Castillo

4/11/2008 11:41:00 AM

SGksIEknbSBkb2luZyBhIHNlcnZlciBhbmQgd2FudCB0byBhdm9pZCBtZW1vcnkgaW5uZWNlc2Fy
eSBvcGVyYXRpb25zLgpJIGhhdmUgYW4gYXJyYXkgb2YgaGVhZGVyczoKICBoZWFkZXJzX2FycmF5
CgpFYWNoIGhlYWRlciBpcyBhbiBvYmplY3Qgb2YgIkhlYWRlciIgY2xhc3M6CgoJY2xhc3MgSGVh
ZGVyCgkJYXR0cl9hY2Nlc3NvciA6bmFtZSwgOmJvZHkKCQlkZWYgaW5pdGlhbGl6ZShuYW1lLCBi
b2R5KQoJCQlAbmFtZSA9IG5hbWUKCQkJQGJvZHkgPSBib2R5CgkJZW5kCgllbmQKCgpUaGVyZSBh
cmUgYWxzbyBvdGhlcnMgc3BlY2lmaWMgaGVhZGVycyBzb29ucyBvZiAiSGVhZGVyIiBjbGFzczoK
CgljbGFzcyBGcm9tIDwgSGVhZGVyCgkJYXR0cl9hY2Nlc3NvciA6dXJpCgllbmQKCgpBdCB0aGUg
YmVnZ2luaW5nICJoZWFkZXJzX2FycmF5IiBqdXN0IGNvbnRhaW4gIkhlYWRlciIgb2JqZWN0cyBi
dXQKYWZ0ZXIgaW5zcGVjdGlvbiBJIHdhbnQgdG8gcmVwbGFjZSB0aGUgaGVhZGVyIHdpdGggQG5h
bWU9J0Zyb20nIHdpdGggYQoiRnJvbSIgb2JqZWN0IGJ1dCBzaW5jZSAibmFtZSIgYW5kICJib2R5
IiBhdHRyaWJ1dGVzIGFyZSB0aGUgc2FtZSBJCmRvbid0IHdhbnQgYSBtZW1vcnkgY29weSBvcGVy
YXRpb24gdG8gYWxsb2NhdGUgc3BhY2UgZm9yIG5ldyBvYmplY3QuCgpUaGlzIGlzOiBJIGp1c3Qg
d2FudCB0byBjaGFuZ2UgdGhlIENsYXNzIG9mIGEgIkhlYWRlciIgb2JqZWN0IHRvCiJGcm9tIiBj
bGFzcywga2VlcGluZyB0aGUgYXR0cmlidXRlcyB3aXRob3V0IG1lbW9yeSBjb3B5IG9wZXJhdGlv
biwgaXMKdGhlcmUgYW55IHdheT8gSSBpbWFnaW5lIGluIEMgSSdkIGRvIGl0IGJ5IHVzaW5nIHBv
aW50ZXJzLgoKClRoYW5rcyBmb3IgYW55IGhlbHAuCgoKCi0tIApJw7Fha2kgQmF6IENhc3RpbGxv
CjxpYmNAYWxpYXgubmV0Pgo=

11 Answers

Joel VanderWerf

4/12/2008 6:07:00 AM

0

Iñaki Baz Castillo wrote:
> Hi, I'm doing a server and want to avoid memory innecesary operations.
> I have an array of headers:
> headers_array
>
> Each header is an object of "Header" class:
>
> class Header
> attr_accessor :name, :body
> def initialize(name, body)
> @name = name
> @body = body
> end
> end
>
>
> There are also others specific headers soons of "Header" class:
>
> class From < Header
> attr_accessor :uri
> end
>
>
> At the beggining "headers_array" just contain "Header" objects but
> after inspection I want to replace the header with @name='From' with a
> "From" object but since "name" and "body" attributes are the same I
> don't want a memory copy operation to allocate space for new object.
>
> This is: I just want to change the Class of a "Header" object to
> "From" class, keeping the attributes without memory copy operation, is
> there any way? I imagine in C I'd do it by using pointers.

Why do you need a From class that is distinct from Header? Depending on
the reason, it might work to make From a module:

module From
# special From methods here
end

headers.each do |h|
if h.name == "From"
h.extend From
end
# or maybe something like:
# h.extend const_get(h.name)
end

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Iñaki Baz Castillo

4/12/2008 8:42:00 PM

0

MjAwOC80LzEyLCBKb2VsIFZhbmRlcldlcmYgPHZqb2VsQHBhdGguYmVya2VsZXkuZWR1PjoKCj4g
IFdoeSBkbyB5b3UgbmVlZCBhIEZyb20gY2xhc3MgdGhhdCBpcyBkaXN0aW5jdCBmcm9tIEhlYWRl
cj8KCkJlY2F1c2UgaW4gYW4gaW5pdGlhbCBwYXJzaW5nIEkganVzdCBnZXQgYSBoZWFkZXJzIGFy
cmF5LCB3aGlvdHUKaW5zcGVjdGluZyBlYWNoIG9mIHRoZW0uCkxhdGVyLCBpZiBJIG5lZWQsIEkg
bG9vayBmb3Igc29tZSBzcGVjaWZpYyBoZWFkZXJzIChGcm9tLCBUby4uLikgYW5kCm5lZWQgdG8g
YWRkIHNvbWUgbWV0aG9kcyB0byB0aGVtLgoKCj4gRGVwZW5kaW5nIG9uIHRoZQo+IHJlYXNvbiwg
aXQgbWlnaHQgd29yayB0byBtYWtlIEZyb20gYSBtb2R1bGU6Cj4KPiAgbW9kdWxlIEZyb20KPiAg
ICMgc3BlY2lhbCBGcm9tIG1ldGhvZHMgaGVyZQo+ICBlbmQKPgo+ICBoZWFkZXJzLmVhY2ggZG8g
fGh8Cj4gICBpZiBoLm5hbWUgPT0gIkZyb20iCj4gICAgIGguZXh0ZW5kIEZyb20KPiAgIGVuZAo+
ICAgIyBvciBtYXliZSBzb21ldGhpbmcgbGlrZToKPiAgICMgaC5leHRlbmQgY29uc3RfZ2V0KGgu
bmFtZSkKPiAgZW5kCgpUaGFua3MsIHRoaXMgaXMgZ3JlYXQhIEkgZGlkbid0IGtub3cgImV4dGVu
ZCIgbWV0aG9kLgoKCi0tIApJw7Fha2kgQmF6IENhc3RpbGxvCjxpYmNAYWxpYXgubmV0Pgo=

Robert Klemme

4/14/2008 1:00:00 PM

0

2008/4/12, I=F1aki Baz Castillo <ibc@aliax.net>:
> 2008/4/12, Joel VanderWerf <vjoel@path.berkeley.edu>:
>
>
> > Why do you need a From class that is distinct from Header?
>
>
> Because in an initial parsing I just get a headers array, whiotu
> inspecting each of them.
> Later, if I need, I look for some specific headers (From, To...) and
> need to add some methods to them.

IMHO it is more efficient and less error prone if you create
appropriate instances during initial parsing. You have all the
information at that point in time plus you you save one additional
pass through the collection.

> > Depending on the
> > reason, it might work to make From a module:
> >
> > module From
> > # special From methods here
> > end
> >
> > headers.each do |h|
> > if h.name =3D=3D "From"
> > h.extend From
> > end
> > # or maybe something like:
> > # h.extend const_get(h.name)
> > end
>
>
> Thanks, this is great! I didn't know "extend" method.

Well, you can even do it during construction:

class Header
attr_accessor :name, :body
def initialize(name, body)
@name =3D name
@body =3D body
extend From if /From/ =3D~ name
end
end

But I'd rather leave the decision to the parsing code.

Cheers

robert

--=20
use.inject do |as, often| as.you_can - without end

Iñaki Baz Castillo

4/14/2008 8:39:00 PM

0

El Lunes, 14 de Abril de 2008, Robert Klemme escribi=F3:
> 2008/4/12, I=F1aki Baz Castillo <ibc@aliax.net>:
> > 2008/4/12, Joel VanderWerf <vjoel@path.berkeley.edu>:
> > > Why do you need a From class that is distinct from Header?
> >
> > Because in an initial parsing I just get a headers array, whiotu
> > inspecting each of them.
> > Later, if I need, I look for some specific headers (From, To...) and
> > need to add some methods to them.
>
> IMHO it is more efficient and less error prone if you create
> appropriate instances during initial parsing. You have all the
> information at that point in time plus you you save one additional
> pass through the collection.

Yes, but let me explain:

I'm doing a SIP protocol parser. In SIP a repeated request can be received=
=20
because retransmissions and there is no need at all of parsing the entire=20
request to know if it's a retransmission (since it will be discarded).
Also, I don't need to parse all the headers, but I cannot know which header=
s=20
I'll need to parse since that is a application layer decission instead of=20
transport layer decission.
=46or example: If I implement a SIp proxy I just need to parse some headers=
, if=20
I do a SIP server UAS I need to parse others. Transport layer is common but=
=20
application layer not, so I don't need to do all the parsing in transport=20
layer.




Thanks a lot for all you suggestions and help. Best regards.


=2D-=20
I=F1aki Baz Castillo

Gary Wright

4/14/2008 9:06:00 PM

0


On Apr 11, 2008, at 7:41 AM, I=F1aki Baz Castillo wrote:
>
> At the beggining "headers_array" just contain "Header" objects but
> after inspection I want to replace the header with @name=3D'From' with =
a
> "From" object but since "name" and "body" attributes are the same I
> don't want a memory copy operation to allocate space for new object.
>
> This is: I just want to change the Class of a "Header" object to
> "From" class, keeping the attributes without memory copy operation, is
> there any way? I imagine in C I'd do it by using pointers.

You can not change the class of an object in Ruby.

You'll have to instantiate a new object and copy the
attributes. If you just do something like:

from_obj.name =3D header_obj.name

You are simply copying object references, you aren't
copying all the associated data.

Gary Wright=

Iñaki Baz Castillo

4/15/2008 12:06:00 AM

0

El Lunes, 14 de Abril de 2008, Gary Wright escribi=F3:
> =A0If you just do something like:
>
> from_obj.name =3D header_obj.name
>
> You are simply copying object references, you aren't
> copying all the associated data.

Hi, that's not true: if an attribute is a String then there will be memory=
=20
copy:

class Header
attr_accessor :name
end

class From
attr_accessor :name
end

header =3D Header.new
header.name =3D "AAAA"
=3D> "AAAA"

from =3D From.new
from.name =3D header.name
=3D> "AAAA"

from.name =3D "BBBB"
=3D> "BBBB"

header.name
=3D> "AAAA"


As you see in the example above if the attribute is a String (or a Fixnum a=
nd=20
so) attribute copy means memory dupplication. Unfortunatelly in my case the=
=20
attribute is a String.

Regards.





=2D-=20
I=F1aki Baz Castillo

Gennady Bystritsky

4/15/2008 1:05:00 AM

0

I=F1aki Baz Castillo wrote:
> El Lunes, 14 de Abril de 2008, Gary Wright escribi=F3:
>> If you just do something like:
>>
>> from_obj.name =3D header_obj.name
>>
>> You are simply copying object references, you aren't
>> copying all the associated data.
>
> Hi, that's not true: if an attribute is a String then there will be
> memory copy:
>
> class Header
> attr_accessor :name
> end
>
> class From
> attr_accessor :name
> end
>
> header =3D Header.new
> header.name =3D "AAAA"
> =3D> "AAAA"
>
> from =3D From.new
> from.name =3D header.name
> =3D> "AAAA"
>
> from.name =3D "BBBB"
> =3D> "BBBB"
>
> header.name
> =3D> "AAAA"
>
>
> As you see in the example above if the attribute is a String (or a
> Fixnum and so) attribute copy means memory dupplication.
> Unfortunatelly in my case the attribute is a String.
>
> Regards.

Not true. To verify it, after you do "from.name =3D header.name", try this:

puts header.name.object_id
puts from.name.object_id

You will see same object id, meaning that you have a reference, not a new o=
bject. To make it a copy, do this:

from.name =3D header.name.dup

Gennady.

Iñaki Baz Castillo

4/15/2008 8:26:00 AM

0

MjAwOC80LzE1LCBHZW5uYWR5IEJ5c3RyaXRza3kgPEdlbm5hZHkuQnlzdHJpdHNreUBxdWVzdC5j
b20+Ogo+IE5vdCB0cnVlLiBUbyB2ZXJpZnkgaXQsIGFmdGVyIHlvdSBkbyAiZnJvbS5uYW1lID0g
aGVhZGVyLm5hbWUiLCB0cnkgdGhpczoKPgo+ICBwdXRzIGhlYWRlci5uYW1lLm9iamVjdF9pZAo+
ICBwdXRzIGZyb20ubmFtZS5vYmplY3RfaWQKPgo+ICBZb3Ugd2lsbCBzZWUgc2FtZSBvYmplY3Qg
aWQsIG1lYW5pbmcgdGhhdCB5b3UgaGF2ZSBhIHJlZmVyZW5jZSwgbm90IGEgbmV3IG9iamVjdC4K
Ck9oaCwgdGhhdCdzIGFubm95aW5nIGZvciBtZSEKWW91IGFyZSByaWdodCwgYm90aCBhcmUgdGhl
IHNhbWUgb2JqZWN0cyAqKnVudGlsKiogSSBtb2RpZnkgb25lIG9mIHRoZW0uIEkgbWVhbjoKCiAg
ZnJvbS5uYW1lID0gaGVhZGVyLm5hbWUKICA9PiAiQUFBQSIKICBmcm9tLm5hbWUuIG9iamVjdF9p
ZCA9PSBoZWFkZXIubmFtZS5vYmplY3RfaWQKICA9PiB0cnVlCgpTbyBpbiB0aGlzIG1vbWVudCBm
cm9tLm5hbWUuIG9iamVjdF9pZCA9PSBoZWFkZXIubmFtZS5vYmplY3RfaWQuIEJ1dAppZiBJIGNo
YW5nZSB0aGUgdmFsdWU6CgogIGZyb20ubmFtZSA9ICJCQkJCIgogIGZyb20ubmFtZS4gb2JqZWN0
X2lkID09IGhlYWRlci5uYW1lLm9iamVjdF9pZAogID0+IGZhbHNlCgpUaGVuIGZyb20ubmFtZS4g
b2JqZWN0X2lkICE9IGhlYWRlci5uYW1lLm9iamVjdF9pZCwgc28gdGhlbiB0aGVyZSBhcmUKdHdv
IHZhbHVlcyBpbiBtZW1vcnkgYXQgc2FtZSB0aW1lLgoKUmVnYXJkcy4KCgotLSAKScOxYWtpIEJh
eiBDYXN0aWxsbwo8aWJjQGFsaWF4Lm5ldD4K

Jesús Gabriel y Galán

4/15/2008 11:19:00 AM

0

On Tue, Apr 15, 2008 at 10:26 AM, I=F1aki Baz Castillo <ibc@aliax.net> wrot=
e:
> 2008/4/15, Gennady Bystritsky <Gennady.Bystritsky@quest.com>:
>
> > Not true. To verify it, after you do "from.name =3D header.name", try t=
his:
> >
> > puts header.name.object_id
> > puts from.name.object_id
> >
> > You will see same object id, meaning that you have a reference, not a=
new object.
>
> Ohh, that's annoying for me!
> You are right, both are the same objects **until** I modify one of them.=
I mean:

This sentence is confusing: you don't modify one of them, you assign
the variable
a different object:

a =3D "header"
b =3D a

a --------> "header"
^
|
|
b


b =3D "new header"

a --------> "header"
b --------> "new header"

The object previously referenced by both a and b has not been modified.
When you assigned a new string to b, then b referenced a different object.

Jesus.

Gennady Bystritsky

4/15/2008 3:43:00 PM

0

I=F1aki Baz Castillo wrote:
> 2008/4/15, Gennady Bystritsky <Gennady.Bystritsky@quest.com>:
>> Not true. To verify it, after you do "from.name =3D header.name", try
>> this:
>>
>> puts header.name.object_id
>> puts from.name.object_id
>>
>> You will see same object id, meaning that you have a reference, not
>> a new object.
>
> Ohh, that's annoying for me!
> You are right, both are the same objects **until** I modify
> one of them. I mean:
>
> from.name =3D header.name
> =3D> "AAAA"
> from.name. object_id =3D=3D header.name.object_id
> =3D> true
>
> So in this moment from.name. object_id =3D=3D header.name.object_id. But
> if I change the value:
>
> from.name =3D "BBBB"
> from.name. object_id =3D=3D header.name.object_id
> =3D> false
>
> Then from.name. object_id !=3D header.name.object_id, so then there are
> two values in memory at same time.
>
> Regards.

You do not change the value, you just assign a reference to a new string. T=
o change the content of a string object you need to use replace() on it. It=
looks like it omits you that "AAAA" and "BBBB" make string objects already=
and not just when you assign them to a variable.

Gennady.