Lifecycle of Elements
Elements, ElementPures, ElementShadowed, Context and
Shadows) are shared accross any number of compound objects. Therefore
once in use, they are immutable. That eliminates need for their
synchronization. Element fields of ElementContainer are
generated on first use - through deferred evaluation, which is
Initially there are only seed Elements. In order to construct new
Elements, create an instance of ElementMutant subclass based on given
original Element. Once all modifications are committed to
ElementMutant, it gets fixed.
Result is available from the start of mutation. However, its
fields can't be accessed before the mutation is fixed.
That's because its mirrors are not finished yet, and therefore its
Context can't be created. Therefore the result can't be passed
or returned from any application methods during the mutation.
It can be stored in a reference field or be a target of a
mirror in another mutation, or even in its own mutation. Inactive
Element can't be an original of any mirror. Otherwise an ElementPure
could be mirrored within its own Context, or within Context of its
components - tricky.
Any access to ElementMutant must be synchronized or
locked. ElementMutant can't accept any changes once
it is fixed.
ElementMutant subclass can't process any application-specific methods
like the ones in Element subclasses. If
ElementMutant queried its components without returning them out, it
would need to wrap them within a Context of that
ElementMutant. Such a Context would be
changeable while ElementMutant is in use, because its mirrors can be
Reason for Mirrors and Context:
We want to share parts of cyclic graphs among several mutations. That
involves mirrors. Mutations without mirrors allow only
- primitive fields
- non-cyclic graphs - relaxed
- child nodes can be
referred to from several parents
- no loops