eclipse-ocl / org.eclipse.ocl

Eclipse Public License 2.0
0 stars 0 forks source link

[pivot] Rationalize specialization/orphan GC - eDispose() #2286

Open eclipse-ocl-bot opened 1 month ago

eclipse-ocl-bot commented 1 month ago

| --- | --- | | Bugzilla Link | 581760 | | Status | NEW | | Importance | P3 normal | | Reported | Apr 03, 2023 03:38 EDT | | Modified | Apr 25, 2023 03:41 EDT | | Depends on | 581860 | | Reporter | Ed Willink |

Description

testEdit_StaleReference_ecore checks that an obsolete specialization is GCed. It relies on the use of WeakReferences to respond to the obsolete type. Surely we can do better and avoid the overheads of WeakReferences?

Simplistically we want to respond to the removal of a TypedElement.type reference, which could be achieved by making it bidirectional, but then e.g. String would have numerous stable opposites. We could be 'naughty' and only maintain the opposite for potential orphans, but naughty modeling often bites downstream.

But the TypedElement.type reference may not actually be removed. When the referenced type is obsoleted, it is not wiped.

Ah! The TypedElement.type reference may not actually be removed. There should be an 'eDispose()' that wipes the object. Well eBasicSetContainer() is pretty close. Given an appropriate integration with the resetContainer() child-stealing detector to support a move without an eDispose(), we can at least detect the need to release the specialization promptly.

But how? a simple share count on the potential orphan can be simple and lightweight but difficult to debug. A full list of sharers might be an option for debugging. An indirect Map<'Orphan', 'Share-count/list'> maintained by the relevant orphan manager avoids bloating non-orphans.

Element.eDispose() traverses all references and sets them to null.

e.g. TypedElement.setType() is overloaded to add/remove the share maintained by an Orphanage.\ ---------------------\ Traditional Model-wise:

TypedElement.type to Type is a regular unidirectional reference.

Type is singly contained either within the user hierarchy or by an Orphanage.

Sharing is unmodelled.\ ---------------------\ Model-wise defining a semantiics of shared containment:

TypedElement.type to Type is a unidirectional shared containment.

Type is either singly aggregate contained within the user hierarchy or multiply shared contained by an Orphanage.

(If the eContainer of a just-shared containment object is null, it can co-exist with the non-null aggregate containment.)

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 24, 2023 03:38

Once the WeakRefs are removed testEdit_Paste_OCLinEcore demonstrates the major problem that a stale Type can be retrived by TypeId from the Orphanage caches.

This can be avoided by checking that any potential return value from the cache isWellContained() all transitove tupes have an eResource().

This leaves the minor problem that stale types are not GCed as diagnosed by testEdit_StaleReference_ecore.

A full sharers/share-count implementation is not needed. We only need to relinquish stale content within the Orphanage. Detection of stale references could be achieved by intercepting all Type/Package/Model eBasicSetContainer().

But why bother with all the overheads for regular usage? The problem only exists for long running applications that mutate() heavily. We can instead provide a gc() method that scans the Orphanage cache and just prunes that that fail isWellContained(). No cost for normal applicatins, and quite possibly cheaper for mutating applications that invoke the gc() method sparingly.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 24, 2023 05:15

(In reply to Ed Willink from comment #1)

A full sharers/share-count implementation is not needed.

No. testEdit_StaleReference_ecore renames to change Boolean to Sequence(MyType) then renames Sequence(MyType) to Set(MyType). MyType is at all times well-contained. Sequence(MyType)can only be detected as stale as a consequence of no-reference.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 24, 2023 09:55

(In reply to Ed Willink from comment #2)

Sequence(MyType)can only be detected as stale as a consequence of no-reference.

And it's not the obvious TypedElement.type case, rather Class.superClasses.

Unfortunately during XMI load the containment tree is missing so we cannot locate the Orphanage in order to maintain any share 'counts'. Rather the local orphanage is populated directly. However since it is only the shared orphanage that needs share 'count's so perhaps the rationalization of load/installResource will solve it all.

Or perhaps we need to implement ResourceHandler.postload.

NB PivotXMIHelperImpl was designed for save but is used during load too. Fix.

eclipse-ocl-bot commented 1 month ago

By Ed Willink on Apr 25, 2023 03:41

(In reply to Ed Willink from comment #3)

Unfortunately during XMI load the containment tree is missing

Not a problem. It is the orphanage of the Tyoe not the TypedElement that is relevant and we cannot be trying to install an orphan when there is no orphanage.


Regularising type specializations in the orphanage hits a prpb;em creating a unqiue typeid for a wildcard. See Bug 581860.