package pt.ist.fenixframework.pstm; import jvstm.VBoxBody; // This version of the VBox exists only because the special needs of // a RelationList which holds a SoftReference to its VBox. // For further explanations see the comment on the class SpecialBody at the end of this file class SoftReferencedVBox extends ReferenceBox { public SoftReferencedVBox() { super(); } public SoftReferencedVBox(E initial) { super(initial); } protected SoftReferencedVBox(VBoxBody body) { super(body); } @Override public VBoxBody commit(E newValue, int txNumber) { // see comment on the class SpecialBody at the end of this file VBoxBody newBody = new SpecialBody(newValue, txNumber, this.body, this); this.body = newBody; return newBody; } public static VBox makeNew(boolean allocateOnly) { if (allocateOnly) { // when a box is allocated, it is safe // to say that the version number is 0 return new SoftReferencedVBox(makeNewBody((T)NOT_LOADED_VALUE, 0, null)); } else { return new SoftReferencedVBox(); } } /* * This SpecialBody class is a hack that will eventually disappear. * It is a simple extension of a MultiVersionBoxBody so that it holds a * strong reference to the box which is owning it. Instances of this class * are created only during the processing of an AlientTransaction * (see TransactionChangeLogs) when a new version is added to a RelationList. * Because RelationLists use a SoftReference to keep the VBox (so that the * bi-directional relations do not prevent the GC from working), it could happen * that the VBox of a RelationList got GCed after the processing of an AlientTransaction * but before older running transactions finished. If meanwhile a more recent transaction * accessed the RelationList, it would load its value and associate it with version 0, which * is wrong. So, until the AlientTransaction gets cleaned up (see the * TransactionChangeLogs.cleanOldAlienTxs method), we must prevent that the VBox be GCed. * This class ensures it, because the AlientTransaction keeps strong a reference to an instance of * this class which has also a strong reference to the VBox. * Finally, when the cleanOldAlienTxs method runs and calls the freeResources on the AlienTransaction, * it calls the clearPrevious method of each body, which, in this case, also removes the reference to * the VBox. * * It's a *little* bit confusing, I know, but... */ private static class SpecialBody extends VBoxBody { private VBox owner; SpecialBody(E value, int version, VBoxBody next, VBox owner) { super(value, version, next); this.owner = owner; } public void clearPrevious() { super.clearPrevious(); // loose the reference to the owner so that it may be GCed, if needed owner = null; } } }