1818
1919import java .io .*;
2020import java .util .*;
21- import java .util .Map .*;
21+ import java .util .concurrent .*;
22+ import java .util .concurrent .atomic .*;
2223import java .util .function .*;
2324import 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
13051307Rectangle 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 */
13841387public 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