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