]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/disposable/AbstractDisposable.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.utils.datastructures / src / org / simantics / utils / datastructures / disposable / AbstractDisposable.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12
13 /*
14  *
15  * @author Toni Kalajainen
16  */
17 package org.simantics.utils.datastructures.disposable;
18
19 import java.lang.reflect.Method;
20
21 import org.simantics.utils.threads.IThreadWorkQueue;
22 import org.simantics.utils.threads.SyncListenerList;
23
24 /**
25  * Base implementation of IDisposable. The subclass must implement doDispose()
26  * method. It invoked at once in first dispose call. Subsequent calls to dispose
27  * throws an AssertionError.
28  * <p>
29  * assertNotDisposed() ensures that the object has not beed disposed. If so,
30  * AssertionError is thrown. assertNotDisposed() should be installed in all
31  * public methods of subclass.
32  * <p>
33  * Object is disposed in finalize, if dispose has not been invoked explicitely.
34  */
35 public abstract class AbstractDisposable implements IDisposable {
36
37     SyncListenerList<IDisposeListener> disposeListeners = null;
38
39     private DisposeState disposeStatus = DisposeState.Alive;
40
41     protected void assertNotDisposed() {
42         if (isDisposed())
43             throw new AssertionError(this + " is disposed.");
44     }
45
46     @Override
47     public DisposeState getDisposeState() {
48         return disposeStatus;
49     }
50     
51     public boolean isDisposed() {
52         return disposeStatus == DisposeState.Disposed;
53     }
54     
55     public boolean isAlive() {
56         return disposeStatus == DisposeState.Alive;
57     }
58     
59     @Override
60     public void dispose() {
61         try {
62             synchronized (this) {
63                 if (disposeStatus == DisposeState.Disposing)
64                     return;
65                 assertNotDisposed();
66                 disposeStatus = DisposeState.Disposing;
67             }
68             try {
69                 fireDisposed();
70             } finally {
71                 doDispose();
72             }
73         } finally {
74             synchronized(this) {
75                 disposeStatus = DisposeState.Disposed;
76             }
77         }
78     }
79     
80     /**
81      * Disposes if not disposed
82      */
83     public void safeDispose() {        
84         try {
85             synchronized (this) {
86                 if (disposeStatus != DisposeState.Alive)
87                     return;
88                 disposeStatus = DisposeState.Disposing;
89             }
90             try {
91                 fireDisposed();
92             } finally {
93                 doDispose();
94             }
95         } finally {
96             synchronized(this) {
97                 disposeStatus = DisposeState.Disposed;
98             }
99         }
100     }
101
102     /**
103      * Do dispose procedures. This method is invoked at most once.
104      */
105     protected abstract void doDispose();
106
107     protected boolean hasDisposeListeners() {
108         return disposeListeners!=null && !disposeListeners.isEmpty();
109     }
110
111     private final static Method onDisposed = SyncListenerList.getMethod(IDisposeListener.class, "onDisposed");
112
113     private void fireDisposed() {
114         if (disposeListeners==null) return;
115         disposeListeners.fireEventSync(onDisposed, this);
116     }
117
118     @SuppressWarnings("unused")
119     private void fireDisposedAsync() {
120         if (disposeListeners==null) return;
121         disposeListeners.fireEventAsync(onDisposed, this);
122     }
123
124     @Override
125     public void addDisposeListener(IDisposeListener listener) {
126         lazyGetListenerList().add(listener);
127     }
128
129     @Override
130     public void addDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
131         lazyGetListenerList().add(thread, listener);
132     }
133
134     @Override
135     public void removeDisposeListener(IDisposeListener listener) {
136         if (disposeListeners==null) return;
137         disposeListeners.remove(listener);
138     }
139
140     @Override
141     public void removeDisposeListener(IDisposeListener listener, IThreadWorkQueue thread) {
142         if (disposeListeners==null) return;
143         disposeListeners.remove(thread, listener);
144     }
145     
146     private synchronized SyncListenerList<IDisposeListener> lazyGetListenerList()
147     {
148         if (disposeListeners==null)
149             disposeListeners = new SyncListenerList<IDisposeListener>(IDisposeListener.class);
150         return disposeListeners;
151     }
152     
153     /*
154     @Override
155     protected void finalize() throws Throwable {
156         try {
157             safeDispose();
158         } finally {
159             super.finalize();
160         }
161     }
162     */
163     
164 }