1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
15 * @author Toni Kalajainen
\r
17 package org.simantics.utils.datastructures.disposable;
\r
19 import java.lang.reflect.Method;
\r
21 import org.simantics.utils.threads.IThreadWorkQueue;
\r
22 import org.simantics.utils.threads.SyncListenerList;
\r
25 * Base implementation of IDisposable. The subclass must implement doDispose()
\r
26 * method. It invoked at once in first dispose call. Subsequent calls to dispose
\r
27 * throws an AssertionError.
\r
29 * assertNotDisposed() ensures that the object has not beed disposed. If so,
\r
30 * AssertionError is thrown. assertNotDisposed() should be installed in all
\r
31 * public methods of subclass.
\r
33 * Object is disposed in finalize, if dispose has not been invoked explicitely.
\r
35 public abstract class AbstractDisposable implements IDisposable {
\r
37 SyncListenerList<IDisposeListener> disposeListeners = null;
\r
39 private DisposeState disposeStatus = DisposeState.Alive;
\r
41 protected void assertNotDisposed() {
\r
43 throw new AssertionError(this + " is disposed.");
\r
47 public DisposeState getDisposeState() {
\r
48 return disposeStatus;
\r
51 public boolean isDisposed() {
\r
52 return disposeStatus == DisposeState.Disposed;
\r
55 public boolean isAlive() {
\r
56 return disposeStatus == DisposeState.Alive;
\r
60 public void dispose() {
\r
62 synchronized (this) {
\r
63 if (disposeStatus == DisposeState.Disposing)
\r
65 assertNotDisposed();
\r
66 disposeStatus = DisposeState.Disposing;
\r
74 synchronized(this) {
\r
75 disposeStatus = DisposeState.Disposed;
\r
81 * Disposes if not disposed
\r
83 public void safeDispose() {
\r
85 synchronized (this) {
\r
86 if (disposeStatus != DisposeState.Alive)
\r
88 disposeStatus = DisposeState.Disposing;
\r
96 synchronized(this) {
\r
97 disposeStatus = DisposeState.Disposed;
\r
103 * Do dispose procedures. This method is invoked at most once.
\r
105 protected abstract void doDispose();
\r
107 protected boolean hasDisposeListeners() {
\r
108 return disposeListeners!=null && !disposeListeners.isEmpty();
\r
111 private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");
\r
113 private void fireDisposed() {
\r
114 if (disposeListeners==null) return;
\r
115 disposeListeners.fireEventSync(onDisposed, this);
\r
118 @SuppressWarnings("unused")
\r
119 private void fireDisposedAsync() {
\r
120 if (disposeListeners==null) return;
\r
121 disposeListeners.fireEventAsync(onDisposed, this);
\r
125 public void addDisposeListener(IDisposeListener listener) {
\r
126 lazyGetListenerList().add(listener);
\r
130 public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
\r
131 lazyGetListenerList().add(thread, listener);
\r
135 public void removeDisposeListener(IDisposeListener listener) {
\r
136 if (disposeListeners==null) return;
\r
137 disposeListeners.remove(listener);
\r
141 public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
\r
142 if (disposeListeners==null) return;
\r
143 disposeListeners.remove(thread, listener);
\r
146 private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()
\r
148 if (disposeListeners==null)
\r
149 disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);
\r
150 return disposeListeners;
\r
155 protected void finalize() throws Throwable {
\r