non-generative record types and classes
Matthias Radestock <[email protected]> Thu, 03 Nov 2005 11:43:30 +0000
| Newsgroups | gmane.comp.java.sisc.devel |
|---|---|
| Message-ID | <[email protected]> |
Currently record and object serialisation is broken because records/objects refer to their type, and type equivalence is based on pointer equality, which serialisation breaks. This issue is documented in bug 806864 and we previously discussed solutions in the "interned objects" thread. It turns out that the interned objects approach suffers from a number of short-comings: - It requires equality on types to work during deserialisation. This is actually quite hard because a) types are often structures with circularities, for which equals? breaks, b) the way references are handled by the serialisation framework would require the type equality to work with a partially deserialised type, which is plainly impossible. - It ends up serialising the entire type structure, even though in most cases will be present in the heap already at deserialisation time. This is inefficient. An alternative approach is get the programmer to tell us which types should be considered equal by supplying a GUID. srfi-76 proposes something like this in the shape of non-generative records. Non-generative types solve the above problems. They are not without shortcomings though. The main one is that if one bases type equality on GUIDs then the programmer can easily shoot themselves in the foot by supplying the same GUID for two types that cannot sensibly be considered to be equal. I think that's something we can live with though. I've been thinking about how to best implement non-generative types in sisc. There is one quite easy and elegant solution: We can take advantage of the fact that references to entries in named symbolic environments are serialised by name. We create a special symbolic environment for types. Creating a non-generative type creates a binding from the guid to that type in that environment. Then, rather than storing a reference to the type in its instances we store a thunk that returns the type. The thunk references the guid and we compile it in the special type environment. Operations like |record-type| and |type-of| are modified to evaluate the thunk. This can all be done in Scheme, and quite easily. The problem is that it only solves the problem of *instance* serialisation, not type serialisation. Specifically, if one tries to serialise anything that references the type directly then problems will still arise. The question, which I cannot immediately answer, is how common that is. For example, when types are defined inside modules since then they effectively become lexically bound to variables which are in scope in all the module's functions and hence they would be part of any continuations captured inside those functions. However, sisc performs accurate capture analysis, so the bindings would be excluded unless they are actually referenced. Can anybody come up with some real-world scenarios where type capture would occur, and cannot be easily circumvented? The alternative solution is to add a bijective map between guids and types (or any values, really) to the application context, and make it part of heap (de)serialisation. The map is updated when non-generative types are defined. Value serialisation would check whether the map contains a binding for the value and if so serialise the guid. Deserialisation would resolve guids by lookups in the map. This is somewhat less neat than the symenv solution. However, it does have the added advantage of offering a general api for serialising values by name: ;;remove any existing mapping for value and guid, and establish the new ;;mapping (register-named-value guid value) Matthias. ------------------------------------------------------- SF.Net email is sponsored by: Tame your development challenges with Apache's Geronimo App Server. Download it for free - -and be entered to win a 42" plasma tv or your very own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php