Components shouldn't be returned out of graph root's Context -
unless that's the purpose. They can be translated (mirrored) to different
Elements within that graph. When they are passed outside Context of
these mirrors, they get resolved to their originals.
Mirrored targets can't keep their mirrored identity outside
the
graph where they are mirrored. Otherwise
the components would need to
be mirrored at top-level
such global mirrors would
affect other graphs, which is against
granularity and encapsulation of local Contexts
or these Elements would need
to be returned by value
that creates Element with
new identity, so any previous mirrors
don't apply to the Element
or the graph would
have to be deep-copied
Cyclic graphs
TODO
OLD - When a Mutation can't be
referenced as an Element before it's fixed:
ElementShadowed and ElementPure graphs themselves can't be recursive.
That's without considering any mirrors. ElementMutants can't create
recurrent paths, because a result of mutation can't be referenced
before it's fixed. See the reasons below.
Graph of Elements can be cyclic. That requires an ElementContainer
which wraps the graph itself. The graph is a mutation of original
graph, and it stores a reference to original graph. That's a backward
reference. It doesn't involve recursion yet, because it links to old
version of the graph and not to the new one. We enclose the graph in an
ElementContainer wrapper, which mirrors the old net's root to its
mutation. That makes the backward reference point to the new graph.
Therefore the resultant net is recursive.
lifecycle of ElementMutant implies that graphs of
ElementShadowed themselves are never cyclic
therefore reference counting can be used for garbage
management of ElementShadowed
graphs of Elements can be cyclic
backward reference
reference from within a mutated graph to root of the original
graph
the reference itself is not recursive
when the gate of the mutated graph mirrors the old graph to new
one, then the reference becomes recursive
gate to a graph
Element (or ElementShadowed/ElementPure) which is not a part of
the graph. It serves as a handle of that graph.
It is a wrapper which keeps mirrors that apply to the whole
graph. Usually it translates old graph to its new version. Then a
backward reference becomes a recursive link to the current graph.
It carries top-level Context of the graph. The graph may become
old when passed out of this Context.
It is a boundary where the graph should be kept. Visitor
mechanism is used to query the graph from outside.
TODO
Recursive objects without graph's gate?
-- Mutation would need to be accessible as Element ( ElementPure with
Shadows.EMPTY with Context ) before it is fixed
TODO Mutation's result
-- how to assure that Element counterpart of unfixed Mutation won't be
accessed (other than just stored) before it's fixed?
-- multithreading
---- if such Element counterpart is stored in a different thread, then
synchronization will need to be used
---- no need for synchronization:
------ 'unfixed' ElementPure will have original, values & mirrors
set to null
------ once mutation is fixed, it uses java.reflect.Accessible to set
these final null fields
------ it insures that unfixed ElementPure won't make any harm if used
as 'fixed', but throws NullPointerException
------ therefore: if unfixed ElementPure is used in a different thread,
it's application's responsibility to synchronized it; otherwise it
might fail
- Context of unfixed ElementPure
---- MirrorsOwner chains would need to be updated
---- therefore unfixed ElementPure can't be used there
---- that's what ElementPure.fixed field will be for - to check whether
the object is fixed