Having completed my Smalltalk parser and gotten quite a few snazzy
things to work, I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. Currently, my proxy objects have no instance variables other than their own OOP and a pointer to the connection they came from. Objects that are returned by messages to these instances are autoreleased, meaning that it is the responsibility of the calling application to retain them if they plan to refer to them. This precludes these objects from being used in more complex UIs. For example, if I have class Person with an instance variable called "pets" which contains an array of objects of class Animal, in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. I have been looking at the GemTools code to see if I could figure out how this is being handled there but I honestly can't seem to nail it down. If you could point me in the right direction, it would be much appreciated. I guess the right behaviour would be: if the result of a message sent to object X is one of X's instance variables, it should be retained by that object Thanks, Eli |
Eli,
Glad to hear about the progress on your tools. As to the garbage collection issue, it would help me understand things if you would be quite explicit about which object space applies. I assume you are dealing entirely with the Cocoa object space, but I just want to be sure. If so, then your problem sounds more like a Cocoa problem than a GemStone problem. From my limited understanding of manual garbage collection in Cocoa, it makes sense that any objects that you don't explicit retain will be lost. (Are you avoiding automatic garbage collection so you can run on the mobile devices?) Be forewarned that attempting to coordinate two object spaces is a very complex activity. A simpler approach is to go back to the server on each event to get the required data to display; and the display data should probably be simplified (e.g., mostly strings). So when you click on a person, go to the server and get a tab-delimited string with a list of pets. This is the approach I've taken with Jade, and it seems to work well for the tools. James On May 25, 2010, at 9:38 AM, Eli Green wrote: > Having completed my Smalltalk parser and gotten quite a few snazzy > things to work, I am now interested in trying to work with more > complex objects and have run into a snag related to garbage > collection. > > Currently, my proxy objects have no instance variables other than > their own OOP and a pointer to the connection they came from. Objects > that are returned by messages to these instances are autoreleased, > meaning that it is the responsibility of the calling application to > retain them if they plan to refer to them. This precludes these > objects from being used in more complex UIs. > > For example, if I have class Person with an instance variable called > "pets" which contains an array of objects of class Animal, in Cocoa > using bindings, I could create a list of people and when a person is > selected in the list, I could automatically populate a second list > with their pets. This is the theory, but it doesn't work because > between the "pets" array is being garbage collected since my proxy > doesn't retain it. > > I have been looking at the GemTools code to see if I could figure out > how this is being handled there but I honestly can't seem to nail it > down. If you could point me in the right direction, it would be much > appreciated. > > I guess the right behaviour would be: > > if the result of a message sent to object X is one of X's instance > variables, it should be retained by that object > > Thanks, > Eli > |
In reply to this post by Eli Green-5
On May 25, 2010, at 18:56, James Foster wrote: > Eli, > > Glad to hear about the progress on your tools. As to the garbage collection issue, it would help me understand things if you would be quite explicit about which object space applies. I assume you are dealing entirely with the Cocoa object space, but I just want to be sure. If so, then your problem sounds more like a Cocoa problem than a GemStone problem. From my limited understanding of manual garbage collection in Cocoa, it makes sense that any objects that you don't explicit retain will be lost. (Are you avoiding automatic garbage collection so you can run on the mobile devices?) > > Be forewarned that attempting to coordinate two object spaces is a very complex activity. A simpler approach is to go back to the server on each event to get the required data to display; and the display data should probably be simplified (e.g., mostly strings). So when you click on a person, go to the server and get a tab-delimited string with a list of pets. This is the approach I've taken with Jade, and it seems to work well for the tools. > > James > Hi James, The garbage collection problems I am referring to are indeed in Cocoa. If I want to fetch strings and numbers then there aren't any problems; I can just store them in an array in the controller class and not worry about it. This is what I'm doing up until now with the browser list views. But I would like to keep references to the objects themselves rather than just values. Cocoa is definitely object oriented and it's almost easier to deal with a set of domain objects than it is to continually set and get values from form objects. The grand experiment I'm performing is to see whether it can be made seamless with GemStone as a back-end object store. Unfortunately Apple's UI classes have a nasty habit of making assumptions about what you're going to retain and so just because you return an object for display doesn't mean they're going to retain it themselves. I'm avoiding garbage collection because it's the easier case and I'd rather program for the hard case and later test under the easy one. But I would have the same problem with garbage collection, it just might alter when the crashes occur. I guess it's back to the drawing board for now. :) I will dive into the GemTools proxy classes and see if they illuminate things for me. Eli |
In reply to this post by Eli Green-5
So, you are serializing an object and sending it elsewhere. The loading objectspace knows of a remote oop and connection. You are having problems...
>> I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. That means either epoch is running or you have a bug in your code related to roll back of object state. >> in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. No idea what Cocoa bindings are, but I presume they like any other binding in that they act like a placeholder for information. Your object is referring to the binding--and your binding is referring to lazy-initialized data. A classic lazy initialization problem. Need to avoid lazy-initialization in GS because their values get rolled back to un-initialized state and you end up doing the work far more frequently than intended. Since you are doing lazy-initialization by design for proxies, you need to do it through indirection. The binding should be a reference into what I refer to as a session-oop table later. The binding should not directly reference the session-oop table or else you end up with the same problem. >> if the result of a message sent to object X is one of X's instance variables, it should be retained by that object An object should not stay static because it had previously answered an attribute. Objects change. You want static state then you have to make it that way yourself. A context object can be made to do that, but you should first consider that you may have serialized an oop reference when you should have instead serialized state. If you make every object a reference then performance will suck (just as GBS would suck if it only had forwarders). If you serialize only state then you risk copies of objects you want shared. You need to find a balance that is application-defined. It appears your are taking a system-level approach though. I presume that you are serializing everything except a kind of X (X is saved as a reference with or without state contents). You are probably assigning X.oop upon instance creation/initialization. Consider this approach for oops... Use your own application-defined oop instead of the GS oop. Your oop would be either two unsigned integers or one bit combined one. The first part would be a session identifier. The second part would be an index into an array that was built (and later committed) by that session. The session state array would be created and registered first to avoid chance of commit conflict later. Take this a step further and make the session identifier one that is unique between environments (both sessions and databases). Easy stuff really. The dB can track it's own session-oop tables alone or be extended to have the session-oop tables moved between environments too (redundancy, replication, etc.). Lots of things you can do with that. Your session-oop tables are also a means to manage changes between objectspaces. You'd have a higher level manager that controls export sets and replication of your X objects. I could describe how to do this approach more efficiently, but I'll stop here. Sounds like you are doing some things that are inherent to State Replication Protocol. You can find SRP in the forums section of http://techsupport.gemstone.com. SRP has a very elegant approach to proxies, exchanges, depth rules, and stream indexes. I'm just posted the most recent changes to SRP for you. SRP has been around for a decade but few people know of it. Start with SrpConfiguration and look for class-side #documentation methods. SRP is designed to be extended to have proxies and distributed processing as you are now working on. Paul Baumann -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Eli Green Sent: Tuesday, May 25, 2010 12:38 PM To: GemStone Smalltalk Customer Forum Subject: [gemstone-smalltalk] Mirroring object "ownership" in the parallel object space Having completed my Smalltalk parser and gotten quite a few snazzy things to work, I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. Currently, my proxy objects have no instance variables other than their own OOP and a pointer to the connection they came from. Objects that are returned by messages to these instances are autoreleased, meaning that it is the responsibility of the calling application to retain them if they plan to refer to them. This precludes these objects from being used in more complex UIs. For example, if I have class Person with an instance variable called "pets" which contains an array of objects of class Animal, in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. I have been looking at the GemTools code to see if I could figure out how this is being handled there but I honestly can't seem to nail it down. If you could point me in the right direction, it would be much appreciated. I guess the right behaviour would be: if the result of a message sent to object X is one of X's instance variables, it should be retained by that object Thanks, Eli This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. |
In reply to this post by Eli Green-5
I'm sorry, I don't think I made my problem clear.
I'm not having any garbage collection issues with the GemStone objects - I am trying to create transparent proxies of GemStone objects from the Cocoa (Objective-C) runtime. Objective-C has very similar message-passing semantics to Smalltalk. I am having problems knowing whether to "retain" (keep a pointer to or maintain the reference count) objects that have been returned to me. In Cocoa, "retain" means to increment a reference count and "release" means to decrement it. For a more concrete example, the table view works by requesting information from a delegate. It does this in two phases: first it requests the object for a row it needs to draw and then requests the representation of the cells themselves. The problem is that my object is going out of scope between these two calls and being collected before the second call happens. I need somewhere to attach that object. My question was mostly how (or even if) the GemStone folks had resolved these issues in the GemTools libraries, where I believe they do a similar transparent-proxying system. I have yet to come up with a system that will work 100% reliably. A Cocoa binding is really just dynamic lookup where instead of loading a certain value into an interface widget, you can specify what property should be bound to that widget. For example, if you had a variable called "person" in your controller, you could bind a text field to "person.name" and the value would be accessed using person's "name" getter/setter. Performance is not necessarily a major concern at the moment. I am indeed looking for a system-wide approach because of the nature of the framework I am trying to build (which is a hobby project). Eli On May 25, 2010, at 21:21, Paul Baumann wrote: > So, you are serializing an object and sending it elsewhere. The loading objectspace knows of a remote oop and connection. You are having problems... > >>> I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. > > That means either epoch is running or you have a bug in your code related to roll back of object state. > >>> in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. > > No idea what Cocoa bindings are, but I presume they like any other binding in that they act like a placeholder for information. Your object is referring to the binding--and your binding is referring to lazy-initialized data. A classic lazy initialization problem. Need to avoid lazy-initialization in GS because their values get rolled back to un-initialized state and you end up doing the work far more frequently than intended. Since you are doing lazy-initialization by design for proxies, you need to do it through indirection. The binding should be a reference into what I refer to as a session-oop table later. The binding should not directly reference the session-oop table or else you end up with the same problem. > >>> if the result of a message sent to object X is one of X's instance variables, it should be retained by that object > > An object should not stay static because it had previously answered an attribute. Objects change. You want static state then you have to make it that way yourself. A context object can be made to do that, but you should first consider that you may have serialized an oop reference when you should have instead serialized state. If you make every object a reference then performance will suck (just as GBS would suck if it only had forwarders). If you serialize only state then you risk copies of objects you want shared. You need to find a balance that is application-defined. It appears your are taking a system-level approach though. I presume that you are serializing everything except a kind of X (X is saved as a reference with or without state contents). You are probably assigning X.oop upon instance creation/initialization. > > Consider this approach for oops... > > Use your own application-defined oop instead of the GS oop. Your oop would be either two unsigned integers or one bit combined one. The first part would be a session identifier. The second part would be an index into an array that was built (and later committed) by that session. The session state array would be created and registered first to avoid chance of commit conflict later. Take this a step further and make the session identifier one that is unique between environments (both sessions and databases). Easy stuff really. The dB can track it's own session-oop tables alone or be extended to have the session-oop tables moved between environments too (redundancy, replication, etc.). Lots of things you can do with that. > > Your session-oop tables are also a means to manage changes between objectspaces. You'd have a higher level manager that controls export sets and replication of your X objects. I could describe how to do this approach more efficiently, but I'll stop here. > > Sounds like you are doing some things that are inherent to State Replication Protocol. You can find SRP in the forums section of http://techsupport.gemstone.com. SRP has a very elegant approach to proxies, exchanges, depth rules, and stream indexes. I'm just posted the most recent changes to SRP for you. SRP has been around for a decade but few people know of it. Start with SrpConfiguration and look for class-side #documentation methods. SRP is designed to be extended to have proxies and distributed processing as you are now working on. > > Paul Baumann > > > -----Original Message----- > From: [hidden email] [mailto:[hidden email]] On Behalf Of Eli Green > Sent: Tuesday, May 25, 2010 12:38 PM > To: GemStone Smalltalk Customer Forum > Subject: [gemstone-smalltalk] Mirroring object "ownership" in the parallel object space > > Having completed my Smalltalk parser and gotten quite a few snazzy things to work, I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. > > Currently, my proxy objects have no instance variables other than their own OOP and a pointer to the connection they came from. Objects that are returned by messages to these instances are autoreleased, meaning that it is the responsibility of the calling application to retain them if they plan to refer to them. This precludes these objects from being used in more complex UIs. > > For example, if I have class Person with an instance variable called "pets" which contains an array of objects of class Animal, in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. > > I have been looking at the GemTools code to see if I could figure out how this is being handled there but I honestly can't seem to nail it down. If you could point me in the right direction, it would be much appreciated. > > I guess the right behaviour would be: > > if the result of a message sent to object X is one of X's instance variables, it should be retained by that object > > Thanks, > Eli > > > > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. > > |
In reply to this post by Eli Green-5
No need for reference counting if you have a WeakArray.
I presume Objective-C has the equivalent of a WeakArray. You'll need that. In short, think if two arrays of the same size and used together at all times. One is weak and one is strong. The weak array references objects, the strong array knows the oop for the the object at the same index position in the weak array. Where you find an oop in the strong array but a nil in the weak array then you know the object is no longer referenced in the image and you know the oop of the object to remove from the export set. You can have more than two related arrays if you need to associate more than just Object and oop. The heart of the pattern is the WeakArray though. The rest is just indexing and growth techniques. There are many variations of that basic pattern--and I've created one that is better than anything else. GS iteself doesn't have a WeakArray, but it is possible to create one. Sounds like you just need a WeakArray in Objective-C though. Paul Baumann -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Eli Green Sent: Tuesday, May 25, 2010 4:37 PM To: GemStone Smalltalk Customer Forum Subject: [gemstone-smalltalk] RE: Mirroring object "ownership" in the parallel object space I'm sorry, I don't think I made my problem clear. I'm not having any garbage collection issues with the GemStone objects - I am trying to create transparent proxies of GemStone objects from the Cocoa (Objective-C) runtime. Objective-C has very similar message-passing semantics to Smalltalk. I am having problems knowing whether to "retain" (keep a pointer to or maintain the reference count) objects that have been returned to me. In Cocoa, "retain" means to increment a reference count and "release" means to decrement it. For a more concrete example, the table view works by requesting information from a delegate. It does this in two phases: first it requests the object for a row it needs to draw and then requests the representation of the cells themselves. The problem is that my object is going out of scope between these two calls and being collected before the second call happens. I need somewhere to attach that object. My question was mostly how (or even if) the GemStone folks had resolved these issues in the GemTools libraries, where I believe they do a similar transparent-proxying system. I have yet to come up with a system that will work 100% reliably. A Cocoa binding is really just dynamic lookup where instead of loading a certain value into an interface widget, you can specify what property should be bound to that widget. For example, if you had a variable called "person" in your controller, you could bind a text field to "person.name" and the value would be accessed using person's "name" getter/setter. Performance is not necessarily a major concern at the moment. I am indeed looking for a system-wide approach because of the nature of the framework I am trying to build (which is a hobby project). Eli On May 25, 2010, at 21:21, Paul Baumann wrote: > So, you are serializing an object and sending it elsewhere. The loading objectspace knows of a remote oop and connection. You are having problems... > >>> I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. > > That means either epoch is running or you have a bug in your code related to roll back of object state. > >>> in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. > > No idea what Cocoa bindings are, but I presume they like any other binding in that they act like a placeholder for information. Your object is referring to the binding--and your binding is referring to lazy-initialized data. A classic lazy initialization problem. Need to avoid lazy-initialization in GS because their values get rolled back to un-initialized state and you end up doing the work far more frequently than intended. Since you are doing lazy-initialization by design for proxies, you need to do it through indirection. The binding should be a reference into what I refer to as a session-oop table later. The binding should not directly reference the session-oop table or else you end up with the same problem. > >>> if the result of a message sent to object X is one of X's instance >>> variables, it should be retained by that object > > An object should not stay static because it had previously answered an attribute. Objects change. You want static state then you have to make it that way yourself. A context object can be made to do that, but you should first consider that you may have serialized an oop reference when you should have instead serialized state. If you make every object a reference then performance will suck (just as GBS would suck if it only had forwarders). If you serialize only state then you risk copies of objects you want shared. You need to find a balance that is application-defined. It appears your are taking a system-level approach though. I presume that you are serializing everything except a kind of X (X is saved as a reference with or without state contents). You are probably assigning X.oop upon instance creation/initialization. > > Consider this approach for oops... > > Use your own application-defined oop instead of the GS oop. Your oop would be either two unsigned integers or one bit combined one. The first part would be a session identifier. The second part would be an index into an array that was built (and later committed) by that session. The session state array would be created and registered first to avoid chance of commit conflict later. Take this a step further and make the session identifier one that is unique between environments (both sessions and databases). Easy stuff really. The dB can track it's own session-oop tables alone or be extended to have the session-oop tables moved between environments too (redundancy, replication, etc.). Lots of things you can do with that. > > Your session-oop tables are also a means to manage changes between objectspaces. You'd have a higher level manager that controls export sets and replication of your X objects. I could describe how to do this approach more efficiently, but I'll stop here. > > Sounds like you are doing some things that are inherent to State Replication Protocol. You can find SRP in the forums section of http://techsupport.gemstone.com. SRP has a very elegant approach to proxies, exchanges, depth rules, and stream indexes. I'm just posted the most recent changes to SRP for you. SRP has been around for a decade but few people know of it. Start with SrpConfiguration and look for class-side #documentation methods. SRP is designed to be extended to have proxies and distributed processing as you are now working on. > > Paul Baumann > > > -----Original Message----- > From: [hidden email] > [mailto:[hidden email]] On Behalf > Of Eli Green > Sent: Tuesday, May 25, 2010 12:38 PM > To: GemStone Smalltalk Customer Forum > Subject: [gemstone-smalltalk] Mirroring object "ownership" in the > parallel object space > > Having completed my Smalltalk parser and gotten quite a few snazzy things to work, I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. > > Currently, my proxy objects have no instance variables other than their own OOP and a pointer to the connection they came from. Objects that are returned by messages to these instances are autoreleased, meaning that it is the responsibility of the calling application to retain them if they plan to refer to them. This precludes these objects from being used in more complex UIs. > > For example, if I have class Person with an instance variable called "pets" which contains an array of objects of class Animal, in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. > > I have been looking at the GemTools code to see if I could figure out how this is being handled there but I honestly can't seem to nail it down. If you could point me in the right direction, it would be much appreciated. > > I guess the right behaviour would be: > > if the result of a message sent to object X is one of X's instance > variables, it should be retained by that object > > Thanks, > Eli > > > > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. > > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. |
In reply to this post by Eli Green-5
On May 25, 2010, at 23:21, Paul Baumann wrote: > No need for reference counting if you have a WeakArray. Older versions of Objective-C are entirely based on reference counting, the retain/release messages are implemented by their NSObject class. I would like to support these older versions because garbage collection is not enabled on the iPhone OS. > > I presume Objective-C has the equivalent of a WeakArray. You'll need that. In short, think if two arrays of the same size and used together at all times. One is weak and one is strong. The weak array references objects, the strong array knows the oop for the the object at the same index position in the weak array. Where you find an oop in the strong array but a nil in the weak array then you know the object is no longer referenced in the image and you know the oop of the object to remove from the export set. You can have more than two related arrays if you need to associate more than just Object and oop. The heart of the pattern is the WeakArray though. The rest is just indexing and growth techniques. > There is a weak array in Objective-C but unfortunately when an object is collected, the entry in the weak array is not set to nil, it is left pointing at an invalid memory location. Fortunately I know when to release an oop because objects are sent either "dealloc" or "finalize" messages when they are being deallocated (depending on whether you are using the garbage-collected runtime or not). I am going to start using a weak dictionary to make sure that I don't create two proxy objects pointing to the same oop but it doesn't solve the problem of my proxies being free'd before I'm done with them. What I think I will have to end up doing is make objects contain a set of all the proxies that were returned by messages sent to them, regardless of whether they really own that object or not. It may lead to objects retaining objects that they have no real relationship with but it should avoid leaks and give those objects a home so they don't get deallocated prematurely. Basically Objective-C is a far cry from a real Smalltalk. > There are many variations of that basic pattern--and I've created one that is better than anything else. > > GS iteself doesn't have a WeakArray, but it is possible to create one. Sounds like you just need a WeakArray in Objective-C though. > > Paul Baumann > > > -----Original Message----- > From: [hidden email] [mailto:[hidden email]] On Behalf Of Eli Green > Sent: Tuesday, May 25, 2010 4:37 PM > To: GemStone Smalltalk Customer Forum > Subject: [gemstone-smalltalk] RE: Mirroring object "ownership" in the parallel object space > > I'm sorry, I don't think I made my problem clear. > > I'm not having any garbage collection issues with the GemStone objects - I am trying to create transparent proxies of GemStone objects from the Cocoa (Objective-C) runtime. Objective-C has very similar message-passing semantics to Smalltalk. I am having problems knowing whether to "retain" (keep a pointer to or maintain the reference count) objects that have been returned to me. > > In Cocoa, "retain" means to increment a reference count and "release" means to decrement it. > > For a more concrete example, the table view works by requesting information from a delegate. It does this in two phases: first it requests the object for a row it needs to draw and then requests the representation of the cells themselves. The problem is that my object is going out of scope between these two calls and being collected before the second call happens. I need somewhere to attach that object. > > My question was mostly how (or even if) the GemStone folks had resolved these issues in the GemTools libraries, where I believe they do a similar transparent-proxying system. > > I have yet to come up with a system that will work 100% reliably. > > A Cocoa binding is really just dynamic lookup where instead of loading a certain value into an interface widget, you can specify what property should be bound to that widget. For example, if you had a variable called "person" in your controller, you could bind a text field to "person.name" and the value would be accessed using person's "name" getter/setter. > > Performance is not necessarily a major concern at the moment. I am indeed looking for a system-wide approach because of the nature of the framework I am trying to build (which is a hobby project). > > Eli > > On May 25, 2010, at 21:21, Paul Baumann wrote: > >> So, you are serializing an object and sending it elsewhere. The loading objectspace knows of a remote oop and connection. You are having problems... >> >>>> I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. >> >> That means either epoch is running or you have a bug in your code related to roll back of object state. >> >>>> in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. >> >> No idea what Cocoa bindings are, but I presume they like any other binding in that they act like a placeholder for information. Your object is referring to the binding--and your binding is referring to lazy-initialized data. A classic lazy initialization problem. Need to avoid lazy-initialization in GS because their values get rolled back to un-initialized state and you end up doing the work far more frequently than intended. Since you are doing lazy-initialization by design for proxies, you need to do it through indirection. The binding should be a reference into what I refer to as a session-oop table later. The binding should not directly reference the session-oop table or else you end up with the same problem. >> >>>> if the result of a message sent to object X is one of X's instance >>>> variables, it should be retained by that object >> >> An object should not stay static because it had previously answered an attribute. Objects change. You want static state then you have to make it that way yourself. A context object can be made to do that, but you should first consider that you may have serialized an oop reference when you should have instead serialized state. If you make every object a reference then performance will suck (just as GBS would suck if it only had forwarders). If you serialize only state then you risk copies of objects you want shared. You need to find a balance that is application-defined. It appears your are taking a system-level approach though. I presume that you are serializing everything except a kind of X (X is saved as a reference with or without state contents). You are probably assigning X.oop upon instance creation/initialization. >> >> Consider this approach for oops... >> >> Use your own application-defined oop instead of the GS oop. Your oop would be either two unsigned integers or one bit combined one. The first part would be a session identifier. The second part would be an index into an array that was built (and later committed) by that session. The session state array would be created and registered first to avoid chance of commit conflict later. Take this a step further and make the session identifier one that is unique between environments (both sessions and databases). Easy stuff really. The dB can track it's own session-oop tables alone or be extended to have the session-oop tables moved between environments too (redundancy, replication, etc.). Lots of things you can do with that. >> >> Your session-oop tables are also a means to manage changes between objectspaces. You'd have a higher level manager that controls export sets and replication of your X objects. I could describe how to do this approach more efficiently, but I'll stop here. >> >> Sounds like you are doing some things that are inherent to State Replication Protocol. You can find SRP in the forums section of http://techsupport.gemstone.com. SRP has a very elegant approach to proxies, exchanges, depth rules, and stream indexes. I'm just posted the most recent changes to SRP for you. SRP has been around for a decade but few people know of it. Start with SrpConfiguration and look for class-side #documentation methods. SRP is designed to be extended to have proxies and distributed processing as you are now working on. >> >> Paul Baumann >> >> >> -----Original Message----- >> From: [hidden email] >> [mailto:[hidden email]] On Behalf >> Of Eli Green >> Sent: Tuesday, May 25, 2010 12:38 PM >> To: GemStone Smalltalk Customer Forum >> Subject: [gemstone-smalltalk] Mirroring object "ownership" in the >> parallel object space >> >> Having completed my Smalltalk parser and gotten quite a few snazzy things to work, I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. >> >> Currently, my proxy objects have no instance variables other than their own OOP and a pointer to the connection they came from. Objects that are returned by messages to these instances are autoreleased, meaning that it is the responsibility of the calling application to retain them if they plan to refer to them. This precludes these objects from being used in more complex UIs. >> >> For example, if I have class Person with an instance variable called "pets" which contains an array of objects of class Animal, in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. >> >> I have been looking at the GemTools code to see if I could figure out how this is being handled there but I honestly can't seem to nail it down. If you could point me in the right direction, it would be much appreciated. >> >> I guess the right behaviour would be: >> >> if the result of a message sent to object X is one of X's instance >> variables, it should be retained by that object >> >> Thanks, >> Eli >> >> >> >> This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. >> >> > > > > > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. > > |
In reply to this post by Eli Green-5
>> I am going to start using a weak dictionary to make >> sure that I don't create two proxy objects >pointing >> to the same oop but it doesn't solve the problem of >> my proxies being free'd before I'm done with them. >> What I think I will have to end up doing is make >> objects contain a set of all the proxies that were >> returned by messages sent to them, regardless of >> whether they really own that object or not. That gets into delegates. A delegate is an object that knows the oop and is related (through weak caches) to the proxy/replicate in the client for the oop. A remote oop can be represented in the client image as proxy and/or delegate; both can be weakly referenced and the oop is considered referenced by the client image so long as either is not GC'ed. Caches are indexes for quickly finding a delegate for a proxy and for finding proxy+delegate for oop. While processing traversals, your traversal would temporarily retain a strong reference (like an OrderedCollection) to objects you've unpacked. The strong reference is released after the traversal buffer is unpacked and then the objects (proxies/replicates and delegates) survive only if they are strongly referenced by a domain object. In newer GBS releases the delegate is both a binary oop encoding and object for GC (which actually limits the design from using more efficient techniques). >> Basically Objective-C is a far cry from a real Smalltalk. Sorry to hear that. I've never used it but thought that if I'd ever had to code in a less productive language then that would be one to consider. Paul Baumann -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Eli Green Sent: Wednesday, May 26, 2010 5:02 AM To: GemStone Smalltalk Customer Forum Subject: [gemstone-smalltalk] RE: Mirroring object "ownership" in the parallel object space On May 25, 2010, at 23:21, Paul Baumann wrote: > No need for reference counting if you have a WeakArray. Older versions of Objective-C are entirely based on reference counting, the retain/release messages are implemented by their NSObject class. I would like to support these older versions because garbage collection is not enabled on the iPhone OS. > > I presume Objective-C has the equivalent of a WeakArray. You'll need that. In short, think if two arrays of the same size and used together at all times. One is weak and one is strong. The weak array references objects, the strong array knows the oop for the the object at the same index position in the weak array. Where you find an oop in the strong array but a nil in the weak array then you know the object is no longer referenced in the image and you know the oop of the object to remove from the export set. You can have more than two related arrays if you need to associate more than just Object and oop. The heart of the pattern is the WeakArray though. The rest is just indexing and growth techniques. > There is a weak array in Objective-C but unfortunately when an object is collected, the entry in the weak array is not set to nil, it is left pointing at an invalid memory location. Fortunately I know when to release an oop because objects are sent either "dealloc" or "finalize" messages when they are being deallocated (depending on whether you are using the garbage-collected runtime or not). I am going to start using a weak dictionary to make sure that I don't create two proxy objects pointing to the same oop but it doesn't solve the problem of my proxies being free'd before I'm done with them. What I think I will have to end up doing is make objects contain a set of all the proxies that were returned by messages sent to them, regardless of whether they really own that object or not. It may lead to objects retaining objects that they have no real relationship with but it should avoid leaks and give those objects a home so they don't get deallocated prematurely. Basically Objective-C is a far cry from a real Smalltalk. > There are many variations of that basic pattern--and I've created one that is better than anything else. > > GS iteself doesn't have a WeakArray, but it is possible to create one. Sounds like you just need a WeakArray in Objective-C though. > > Paul Baumann > > > -----Original Message----- > From: [hidden email] > [mailto:[hidden email]] On Behalf > Of Eli Green > Sent: Tuesday, May 25, 2010 4:37 PM > To: GemStone Smalltalk Customer Forum > Subject: [gemstone-smalltalk] RE: Mirroring object "ownership" in the > parallel object space > > I'm sorry, I don't think I made my problem clear. > > I'm not having any garbage collection issues with the GemStone objects - I am trying to create transparent proxies of GemStone objects from the Cocoa (Objective-C) runtime. Objective-C has very similar message-passing semantics to Smalltalk. I am having problems knowing whether to "retain" (keep a pointer to or maintain the reference count) objects that have been returned to me. > > In Cocoa, "retain" means to increment a reference count and "release" means to decrement it. > > For a more concrete example, the table view works by requesting information from a delegate. It does this in two phases: first it requests the object for a row it needs to draw and then requests the representation of the cells themselves. The problem is that my object is going out of scope between these two calls and being collected before the second call happens. I need somewhere to attach that object. > > My question was mostly how (or even if) the GemStone folks had resolved these issues in the GemTools libraries, where I believe they do a similar transparent-proxying system. > > I have yet to come up with a system that will work 100% reliably. > > A Cocoa binding is really just dynamic lookup where instead of loading a certain value into an interface widget, you can specify what property should be bound to that widget. For example, if you had a variable called "person" in your controller, you could bind a text field to "person.name" and the value would be accessed using person's "name" getter/setter. > > Performance is not necessarily a major concern at the moment. I am indeed looking for a system-wide approach because of the nature of the framework I am trying to build (which is a hobby project). > > Eli > > On May 25, 2010, at 21:21, Paul Baumann wrote: > >> So, you are serializing an object and sending it elsewhere. The loading objectspace knows of a remote oop and connection. You are having problems... >> >>>> I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. >> >> That means either epoch is running or you have a bug in your code related to roll back of object state. >> >>>> in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. >> >> No idea what Cocoa bindings are, but I presume they like any other binding in that they act like a placeholder for information. Your object is referring to the binding--and your binding is referring to lazy-initialized data. A classic lazy initialization problem. Need to avoid lazy-initialization in GS because their values get rolled back to un-initialized state and you end up doing the work far more frequently than intended. Since you are doing lazy-initialization by design for proxies, you need to do it through indirection. The binding should be a reference into what I refer to as a session-oop table later. The binding should not directly reference the session-oop table or else you end up with the same problem. >> >>>> if the result of a message sent to object X is one of X's instance >>>> variables, it should be retained by that object >> >> An object should not stay static because it had previously answered an attribute. Objects change. You want static state then you have to make it that way yourself. A context object can be made to do that, but you should first consider that you may have serialized an oop reference when you should have instead serialized state. If you make every object a reference then performance will suck (just as GBS would suck if it only had forwarders). If you serialize only state then you risk copies of objects you want shared. You need to find a balance that is application-defined. It appears your are taking a system-level approach though. I presume that you are serializing everything except a kind of X (X is saved as a reference with or without state contents). You are probably assigning X.oop upon instance creation/initialization. >> >> Consider this approach for oops... >> >> Use your own application-defined oop instead of the GS oop. Your oop would be either two unsigned integers or one bit combined one. The first part would be a session identifier. The second part would be an index into an array that was built (and later committed) by that session. The session state array would be created and registered first to avoid chance of commit conflict later. Take this a step further and make the session identifier one that is unique between environments (both sessions and databases). Easy stuff really. The dB can track it's own session-oop tables alone or be extended to have the session-oop tables moved between environments too (redundancy, replication, etc.). Lots of things you can do with that. >> >> Your session-oop tables are also a means to manage changes between objectspaces. You'd have a higher level manager that controls export sets and replication of your X objects. I could describe how to do this approach more efficiently, but I'll stop here. >> >> Sounds like you are doing some things that are inherent to State Replication Protocol. You can find SRP in the forums section of http://techsupport.gemstone.com. SRP has a very elegant approach to proxies, exchanges, depth rules, and stream indexes. I'm just posted the most recent changes to SRP for you. SRP has been around for a decade but few people know of it. Start with SrpConfiguration and look for class-side #documentation methods. SRP is designed to be extended to have proxies and distributed processing as you are now working on. >> >> Paul Baumann >> >> >> -----Original Message----- >> From: [hidden email] >> [mailto:[hidden email]] On Behalf >> Of Eli Green >> Sent: Tuesday, May 25, 2010 12:38 PM >> To: GemStone Smalltalk Customer Forum >> Subject: [gemstone-smalltalk] Mirroring object "ownership" in the >> parallel object space >> >> Having completed my Smalltalk parser and gotten quite a few snazzy things to work, I am now interested in trying to work with more complex objects and have run into a snag related to garbage collection. >> >> Currently, my proxy objects have no instance variables other than their own OOP and a pointer to the connection they came from. Objects that are returned by messages to these instances are autoreleased, meaning that it is the responsibility of the calling application to retain them if they plan to refer to them. This precludes these objects from being used in more complex UIs. >> >> For example, if I have class Person with an instance variable called "pets" which contains an array of objects of class Animal, in Cocoa using bindings, I could create a list of people and when a person is selected in the list, I could automatically populate a second list with their pets. This is the theory, but it doesn't work because between the "pets" array is being garbage collected since my proxy doesn't retain it. >> >> I have been looking at the GemTools code to see if I could figure out how this is being handled there but I honestly can't seem to nail it down. If you could point me in the right direction, it would be much appreciated. >> >> I guess the right behaviour would be: >> >> if the result of a message sent to object X is one of X's instance >> variables, it should be retained by that object >> >> Thanks, >> Eli >> >> >> >> This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. >> >> > > > > > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. > > This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired. |
Free forum by Nabble | Edit this page |