]> gerrit.simantics Code Review - simantics/3d.git/blob - vtk/src/vtk/vtkJavaMemoryManagerImpl.java
Perform view direction switching via vtkCameraAndSelectorAction
[simantics/3d.git] / vtk / src / vtk / vtkJavaMemoryManagerImpl.java
1 package vtk;
2
3 import java.lang.ref.WeakReference;
4 import java.lang.reflect.Constructor;
5 import java.util.HashMap;
6 import java.util.TreeSet;
7 import java.util.concurrent.locks.ReentrantLock;
8
9 /**
10  * Provide a Java thread safe implementation of vtkJavaMemoryManager. This does
11  * not make VTK thread safe. This only insure that the change of reference count
12  * will never happen in two concurrent thread in the Java world.
13  *
14  * @see vtkJavaMemoryManager
15  * @author sebastien jourdain - sebastien.jourdain@kitware.com
16  */
17 public class vtkJavaMemoryManagerImpl implements vtkJavaMemoryManager {
18   private vtkJavaGarbageCollector garbageCollector;
19   private ReentrantLock lock;
20   private vtkReferenceInformation lastGcResult;
21   private HashMap<Long, WeakReference<vtkObjectBase>> objectMap;
22   private HashMap<Long, String> objectMapClassName;
23
24   public vtkJavaMemoryManagerImpl() {
25     this.lock = new ReentrantLock();
26     this.objectMap = new HashMap<Long, WeakReference<vtkObjectBase>>();
27     this.objectMapClassName = new HashMap<Long, String>();
28     this.garbageCollector = new vtkJavaGarbageCollector();
29   }
30
31   // Thread safe
32   public vtkObjectBase getJavaObject(Long vtkId) {
33     // Check pre-condition
34     if (vtkId == null || vtkId.longValue() == 0) {
35       throw new RuntimeException("Invalid ID, can not be null or equal to 0.");
36     }
37
38     // Check inside the map if the object is already there
39     WeakReference<vtkObjectBase> value = objectMap.get(vtkId);
40     vtkObjectBase resultObject = (value == null) ? null : value.get();
41
42     // If not, we have to do something
43     if (value == null || resultObject == null) {
44       try {
45         // Make sure no concurrency could happen inside that
46         this.lock.lock();
47
48         // Now that we have the lock make sure someone else didn't
49         // create the object in between, if so just return the created
50         // instance
51         value = objectMap.get(vtkId);
52         resultObject = (value == null) ? null : value.get();
53         if (resultObject != null) {
54           return resultObject;
55         }
56
57         // We need to do the work of the gc
58         if (value != null && resultObject == null) {
59           this.unRegisterJavaObject(vtkId);
60         }
61
62         // No-one did create it, so let's do it
63         if (resultObject == null) {
64           try {
65             String className = vtkObjectBase.VTKGetClassNameFromReference(vtkId.longValue());
66             Class<?> c = Class.forName("vtk." + className);
67             Constructor<?> cons = c.getConstructor(new Class<?>[] { long.class });
68             resultObject = (vtkObjectBase) cons.newInstance(new Object[] { vtkId });
69           } catch (Exception e) {
70             e.printStackTrace();
71           }
72         }
73       } finally {
74         this.lock.unlock();
75       }
76     }
77     return resultObject;
78   }
79
80   // Thread safe
81   public void registerJavaObject(Long id, vtkObjectBase obj) {
82     try {
83       this.lock.lock();
84       this.objectMap.put(id, new WeakReference<vtkObjectBase>(obj));
85       this.objectMapClassName.put(id, obj.GetClassName());
86     } finally {
87       this.lock.unlock();
88     }
89   }
90
91   // Thread safe
92   public void unRegisterJavaObject(Long id) {
93     try {
94       this.lock.lock();
95       this.objectMapClassName.remove(id);
96       WeakReference<vtkObjectBase> value = this.objectMap.remove(id);
97
98       // Prevent double deletion...
99       if (value != null) {
100         vtkObjectBase.VTKDeleteReference(id.longValue());
101       } else {
102         throw new RuntimeException("You try to delete a vtkObject that is not referenced in the Java object Map. You may have call Delete() twice.");
103       }
104     } finally {
105       this.lock.unlock();
106     }
107   }
108
109   // Thread safe
110   public vtkReferenceInformation gc(boolean debug) {
111     System.gc();
112     try {
113       this.lock.lock();
114       final vtkReferenceInformation infos = new vtkReferenceInformation(debug);
115       for (Long id : new TreeSet<Long>(this.objectMap.keySet())) {
116         vtkObjectBase obj = this.objectMap.get(id).get();
117         if (obj == null) {
118           infos.addFreeObject(this.objectMapClassName.get(id));
119           this.unRegisterJavaObject(id);
120         } else {
121           infos.addKeptObject(this.objectMapClassName.get(id));
122         }
123       }
124
125       this.lastGcResult = infos;
126       return infos;
127     } finally {
128       this.lock.unlock();
129     }
130   }
131
132   public vtkJavaGarbageCollector getAutoGarbageCollector() {
133     return this.garbageCollector;
134   }
135
136   // Thread safe
137   public int deleteAll() {
138     int size = this.objectMap.size();
139     try {
140       this.lock.lock();
141       for (Long id : new TreeSet<Long>(this.objectMap.keySet())) {
142         this.unRegisterJavaObject(id);
143       }
144     } finally {
145       this.lock.unlock();
146     }
147     return size;
148   }
149
150   public int getSize() {
151     return objectMap.size();
152   }
153
154   public vtkReferenceInformation getLastReferenceInformation() {
155     return this.lastGcResult;
156   }
157 }