]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/disposable/AbstractDisposable.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.utils.datastructures / src / org / simantics / utils / datastructures / disposable / AbstractDisposable.java
diff --git a/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/disposable/AbstractDisposable.java b/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/disposable/AbstractDisposable.java
new file mode 100644 (file)
index 0000000..745e8f0
--- /dev/null
@@ -0,0 +1,164 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+\r
+/*\r
+ *\r
+ * @author Toni Kalajainen\r
+ */\r
+package org.simantics.utils.datastructures.disposable;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+import org.simantics.utils.threads.IThreadWorkQueue;\r
+import org.simantics.utils.threads.SyncListenerList;\r
+\r
+/**\r
+ * Base implementation of IDisposable. The subclass must implement doDispose()\r
+ * method. It invoked at once in first dispose call. Subsequent calls to dispose\r
+ * throws an AssertionError.\r
+ * <p>\r
+ * assertNotDisposed() ensures that the object has not beed disposed. If so,\r
+ * AssertionError is thrown. assertNotDisposed() should be installed in all\r
+ * public methods of subclass.\r
+ * <p>\r
+ * Object is disposed in finalize, if dispose has not been invoked explicitely.\r
+ */\r
+public abstract class AbstractDisposable implements IDisposable {\r
+\r
+    SyncListenerList<IDisposeListener> disposeListeners = null;\r
+\r
+    private DisposeState disposeStatus = DisposeState.Alive;\r
+\r
+    protected void assertNotDisposed() {\r
+        if (isDisposed())\r
+            throw new AssertionError(this + " is disposed.");\r
+    }\r
+\r
+    @Override\r
+    public DisposeState getDisposeState() {\r
+        return disposeStatus;\r
+    }\r
+    \r
+    public boolean isDisposed() {\r
+        return disposeStatus == DisposeState.Disposed;\r
+    }\r
+    \r
+    public boolean isAlive() {\r
+        return disposeStatus == DisposeState.Alive;\r
+    }\r
+    \r
+    @Override\r
+    public void dispose() {\r
+        try {\r
+            synchronized (this) {\r
+                if (disposeStatus == DisposeState.Disposing)\r
+                    return;\r
+                assertNotDisposed();\r
+                disposeStatus = DisposeState.Disposing;\r
+            }\r
+            try {\r
+                fireDisposed();\r
+            } finally {\r
+                doDispose();\r
+            }\r
+        } finally {\r
+            synchronized(this) {\r
+                disposeStatus = DisposeState.Disposed;\r
+            }\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Disposes if not disposed\r
+     */\r
+    public void safeDispose() {        \r
+        try {\r
+            synchronized (this) {\r
+                if (disposeStatus != DisposeState.Alive)\r
+                    return;\r
+                disposeStatus = DisposeState.Disposing;\r
+            }\r
+            try {\r
+                fireDisposed();\r
+            } finally {\r
+                doDispose();\r
+            }\r
+        } finally {\r
+            synchronized(this) {\r
+                disposeStatus = DisposeState.Disposed;\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Do dispose procedures. This method is invoked at most once.\r
+     */\r
+    protected abstract void doDispose();\r
+\r
+    protected boolean hasDisposeListeners() {\r
+        return disposeListeners!=null && !disposeListeners.isEmpty();\r
+    }\r
+\r
+    private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");\r
+\r
+    private void fireDisposed() {\r
+        if (disposeListeners==null) return;\r
+        disposeListeners.fireEventSync(onDisposed, this);\r
+    }\r
+\r
+    @SuppressWarnings("unused")\r
+    private void fireDisposedAsync() {\r
+        if (disposeListeners==null) return;\r
+        disposeListeners.fireEventAsync(onDisposed, this);\r
+    }\r
+\r
+    @Override\r
+    public void addDisposeListener(IDisposeListener listener) {\r
+        lazyGetListenerList().add(listener);\r
+    }\r
+\r
+    @Override\r
+    public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {\r
+        lazyGetListenerList().add(thread, listener);\r
+    }\r
+\r
+    @Override\r
+    public void removeDisposeListener(IDisposeListener listener) {\r
+        if (disposeListeners==null) return;\r
+        disposeListeners.remove(listener);\r
+    }\r
+\r
+    @Override\r
+    public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {\r
+        if (disposeListeners==null) return;\r
+        disposeListeners.remove(thread, listener);\r
+    }\r
+    \r
+    private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()\r
+    {\r
+        if (disposeListeners==null)\r
+            disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);\r
+        return disposeListeners;\r
+    }\r
+    \r
+    /*\r
+    @Override\r
+    protected void finalize() throws Throwable {\r
+        try {\r
+            safeDispose();\r
+        } finally {\r
+            super.finalize();\r
+        }\r
+    }\r
+    */\r
+    \r
+}\r