Provide a Java thread safe implementation of vtkJavaMemoryManager. This does not make VTK thread safe. This only ensures that the change of reference count will never happen in two concurrent threads in the Java world. @see vtkJavaMemoryManager @author sebastien jourdain - sebastien.jourdain@kitwar
| 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(); |
nothing calls this directly
no outgoing calls
no test coverage detected