From 68623b2a89b09108abfb0c2bc1f71cc6f70e6d38 Mon Sep 17 00:00:00 2001 From: jprocter Date: Fri, 12 Jun 2009 15:54:53 +0000 Subject: [PATCH] prevent and keep track of which objects handling element/jv obj synchronizations. --- src/jalview/io/vamsas/DatastoreRegistry.java | 160 ++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/jalview/io/vamsas/DatastoreRegistry.java diff --git a/src/jalview/io/vamsas/DatastoreRegistry.java b/src/jalview/io/vamsas/DatastoreRegistry.java new file mode 100644 index 0000000..21083dd --- /dev/null +++ b/src/jalview/io/vamsas/DatastoreRegistry.java @@ -0,0 +1,160 @@ +package jalview.io.vamsas; + +import java.util.Enumeration; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.Map; + +import uk.ac.vamsas.client.Vobject; + +public class DatastoreRegistry +{ + protected static org.apache.log4j.Logger log = org.apache.log4j.Logger + .getLogger(DatastoreRegistry.class); + + /** + * map between Datastore objects and the objects they are handling- used to + * prevent cycles in the synchronization pattern. Keys are both vamsas objects + * and jalview objects, values are datastore objects. + */ + IdentityHashMap dsObjReg; + + /** + * all datastore items - value is [jvObject,vObject] + */ + IdentityHashMap dsItemReg; + + public DatastoreRegistry() + { + dsObjReg = new IdentityHashMap(); + dsItemReg = new IdentityHashMap(); + } + + /** + * + * @param obj + * @return true if obj is in the registry + */ + public boolean isInvolvedInDsitem(Object obj) + { + return (obj instanceof DatastoreItem) ? dsItemReg.containsKey(obj) + : dsObjReg.containsKey(obj); + } + + /** + * + * @param obj + * @return DatastoreItem associated with obj - or null + */ + public DatastoreItem getDatastoreItemFor(Object obj) + { + if (obj instanceof DatastoreItem) + { + log.debug("Returning DatastoreItem self reference.");// TODO: we could + // store the update + // hierarchy - so + // retrieve parent + // for obj. + return (DatastoreItem) obj; + } + return (DatastoreItem) dsObjReg.get(obj); + } + + public void registerDsObj(DatastoreItem dsitem) + { + synchronized (dsItemReg) + { + Object[] dsregitem = (Object[]) dsItemReg.get(dsitem); + if (dsregitem == null) + { + // create a new item entry + dsregitem = new Object[] + { dsitem.jvobj, dsitem.vobj }; + dsItemReg.put(dsitem, dsregitem); + } + // atomic update of the jv and vobject references in the dsObjReg + synchronized (dsObjReg) + { + // for the jvobject + if (dsitem.jvobj != dsregitem[0]) + { + // overwrite existing involved entries. + if (dsregitem[0] != null) + { + dsObjReg.remove(dsregitem[0]); + } + if ((dsregitem[0] = dsitem.jvobj) != null) + { + dsObjReg.put(dsregitem[0], dsitem); + } + } + // and for the vobject + if (dsitem.vobj != dsregitem[1]) + { + // overwrite existing involved entries. + if (dsregitem[1] != null) + { + dsObjReg.remove(dsregitem[1]); + } + if ((dsregitem[1] = dsitem.vobj) != null) + { + dsObjReg.put(dsregitem[1], dsitem); + } + } + } + } + } + + /** + * Remove dsitem from the registry + * + * @param dsitem + * @return null or last known Object[] { jvobject, vobject } references for + * this dsitem + */ + public Object[] removeDsObj(DatastoreItem dsitem) + { + Object[] dsregitem = null; + synchronized (dsItemReg) + { + synchronized (dsObjReg) + { + dsregitem = (Object[]) dsItemReg.remove(dsitem); + if (dsregitem != null) + { + // eliminate object refs too + if (dsregitem[0] != null) + { + dsObjReg.remove(dsregitem[0]); + } + if (dsregitem[1] != null) + { + dsObjReg.remove(dsregitem[1]); + } + } + } + } + return dsregitem; + } + + protected void finalize() + { + if (dsObjReg != null) + { + Iterator items = dsObjReg.entrySet().iterator(); + // avoid the nested reference memory leak. + while (items.hasNext()) + { + Object[] vals = (Object[]) ((Map.Entry) items.next()).getValue(); + vals[0] = null; + vals[1] = null; + } + items = null; + dsObjReg.clear(); + } + if (dsItemReg!=null) + { + dsItemReg.clear(); + } + } +} -- 1.7.10.2