Skip to content

Commit 8dc9a9f

Browse files
HeikoKlareamartya4256
authored andcommitted
Make ImageHandle & ImageData write ops synchronous
This commit makes the ImageHandle creation and ImageData caching process synchronous to avoid any racing condition and inefficient memory usages. # Conflicts: # bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java # Conflicts: # bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java
1 parent c2e0429 commit 8dc9a9f

1 file changed

Lines changed: 40 additions & 35 deletions

File tree

  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
import java.io.*;
2020
import java.util.*;
21-
import java.util.Map.*;
21+
import java.util.concurrent.*;
22+
import java.util.concurrent.atomic.*;
2223
import java.util.function.*;
2324
import java.util.stream.*;
2425

@@ -138,7 +139,7 @@ public final class Image extends Resource implements Drawable {
138139
private final ImageHandleManager imageHandleManager = new ImageHandleManager();
139140

140141
private class ImageHandleManager {
141-
private Map<Integer, DestroyableImageHandle> zoomLevelToImageHandle = new HashMap<>();
142+
private Map<Integer, DestroyableImageHandle> zoomLevelToImageHandle = new ConcurrentHashMap<>();
142143

143144
InternalImageHandle get(int zoom) {
144145
final DestroyableImageHandle imageHandle = zoomLevelToImageHandle.get(zoom);
@@ -153,15 +154,7 @@ InternalImageHandle getOrCreate(int zoom, Supplier<DestroyableImageHandle> creat
153154
if (zoom == -1) {
154155
return null;
155156
}
156-
157-
DestroyableImageHandle imageHandle = (DestroyableImageHandle) get(zoom);
158-
if (imageHandle != null) {
159-
return imageHandle;
160-
}
161-
162-
imageHandle = creator.get();
163-
zoomLevelToImageHandle.put(zoom, imageHandle);
164-
return imageHandle;
157+
return zoomLevelToImageHandle.computeIfAbsent(zoom, __ -> creator.get());
165158
}
166159

167160
boolean contains(int zoom) {
@@ -181,16 +174,25 @@ Set<Integer> getAllZooms() {
181174
}
182175

183176
void destroyHandles(Predicate<Integer> filter) {
184-
Iterator<Entry<Integer, DestroyableImageHandle>> it = zoomLevelToImageHandle.entrySet().iterator();
185-
while (it.hasNext()) {
186-
Entry<Integer, DestroyableImageHandle> zoomToHandle = it.next();
187-
if (filter.test(zoomToHandle.getKey())) {
188-
DestroyableImageHandle imageHandle = zoomToHandle.getValue();
189-
it.remove();
190-
zoomLevelToImageHandle.remove(imageHandle.zoom(), imageHandle);
191-
imageHandle.destroy();
177+
zoomLevelToImageHandle.entrySet().removeIf(entry -> {
178+
if (filter.test(entry.getKey())) {
179+
entry.getValue().destroy();
180+
return true;
181+
}
182+
return false;
183+
});
184+
}
185+
186+
<R> R executeOnHandle(int zoom, Supplier<DestroyableImageHandle> handleCreator, Function<Optional<InternalImageHandle>,R> executable) {
187+
AtomicReference<R> computedValue = new AtomicReference<>();
188+
zoomLevelToImageHandle.compute(zoom, (key, value) -> {
189+
if (value == null && handleCreator != null) {
190+
value = handleCreator.get();
192191
}
193-
}
192+
computedValue.set(executable.apply(Optional.ofNullable(value)));
193+
return value;
194+
});
195+
return computedValue.get();
194196
}
195197

196198
@Override
@@ -1304,12 +1306,13 @@ public Rectangle getBounds() {
13041306

13051307
Rectangle getBounds(int zoom) {
13061308
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1307-
if (imageHandleManager.contains(zoom)) {
1308-
InternalImageHandle imageMetadata = imageHandleManager.get(zoom);
1309-
Rectangle rectangle = new Rectangle(0, 0, imageMetadata.width(), imageMetadata.height());
1310-
return Win32DPIUtils.scaleBounds(rectangle, zoom, imageMetadata.zoom());
1311-
}
1312-
return this.imageProvider.getBounds(zoom);
1309+
return imageHandleManager.executeOnHandle(zoom, null, imageMetadata -> {
1310+
if (imageMetadata.isPresent()) {
1311+
Rectangle rectangle = new Rectangle(0, 0, imageMetadata.get().width(), imageMetadata.get().height());
1312+
return Win32DPIUtils.scaleBounds(rectangle, zoom, imageMetadata.get().zoom());
1313+
}
1314+
return this.imageProvider.getBounds(zoom);
1315+
});
13131316
}
13141317

13151318
/**
@@ -1383,15 +1386,17 @@ public ImageData getImageData() {
13831386
*/
13841387
public ImageData getImageData (int zoom) {
13851388
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1386-
InternalImageHandle imageHandle = imageHandleManager.get(zoom);
1387-
if (imageHandle != null) {
1388-
return imageHandle.getImageData();
1389-
}
1390-
1391-
if (this.imageProvider.isPersistentImageHandleRequriedForImageData()) {
1392-
return imageHandleManager.getOrCreate(zoom, () -> imageProvider.newImageHandle(new ZoomContext(zoom))).getImageData();
1393-
}
1394-
return this.imageProvider.newImageData(zoom);
1389+
return imageHandleManager.executeOnHandle(zoom, () -> {
1390+
if (this.imageProvider.isPersistentImageHandleRequriedForImageData()) {
1391+
return imageProvider.newImageHandle(new ZoomContext(zoom));
1392+
}
1393+
return null;
1394+
}, imageHandle -> {
1395+
if (imageHandle.isPresent()) {
1396+
return imageHandle.get().getImageData();
1397+
}
1398+
return this.imageProvider.newImageData(zoom);
1399+
});
13951400
}
13961401

13971402
/**

0 commit comments

Comments
 (0)