Skip to content

Conversation

@amartya4256
Copy link
Contributor

This PR introduces ImageHandleManager, an inner class to Image responsible for managing the storage, creation and manipulation of ImageHandles. This class provides methods which can be used to dead with ImageHandle instances inside an image for managing it with convenience while hiding the complexity of how the ImageHandle lifecycle is managed inside itself.

All the places where zoomToImageHandle map is accessed for any purposes is replaced by the wrapper methods provided by ImageHandleManager. Each image initializes a final field imageHandleManager with the instance of ImageHandleManager. Every instance of ImageHandle created within the Image object is registered in the manager itself and the manager is responsible for cleaning the dangling resources when are not supposed to be used anymore or when a cleanup is needed. Also the manager creates handles in a thread-safe way, making sure no 2 consumers create the same handle at the same time.

This fixes vi-eclipse/Eclipse-Platform#562

@amartya4256 amartya4256 marked this pull request as draft December 22, 2025 12:24
Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the idea to wrap the handle-for-zoom mapping into a separate class. That clearly assigns all related management functionality to that class. I would be in favor of extracting the pure refactoring of the management functionality in a dedicated class into a separate PR. That PR will just improve code quality and comprehensibility and not improve thread safety.

You find several questions and proposals in the detailed comments. The probably most essential point is that to my understanding the implementation is not fully thread safe.

In addition, I am not sure if the concept of using a synchronized data structure is fully sufficient for all cases here (e.g., if we also include the rest of the API such as getBounds() and getImageData()). At least the complexity could increase such that ensuring correctness and maintainability becomes complex. Maybe we better see that when we adapt those methods as well, but I could imagine that simply synchronizing write access might be sufficient (as we don't expect multiple consumers to write for different zooms) and provides reduced compexity and error proneness.

return imageHandle;
}
return zoomLevelToImageHandle.get(targetZoom);
return imageHandleManager.getImageHandle(targetZoom);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks a bit weird (but also did before) because we call a _new_ImageHandle method and then return an existing one. From my understanding, this line of code should never be reached anyway. In case there is a memGC, there should also be an image handle for it, so that newImageHandle will never be called unless the zoom of that handle is not fitting (and then the if block above is executed).

long newHandle = drawable.internal_new_GC(newData);
if (newHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
init(drawable, newData, newHandle);
initWithImageHandle(drawable, newData, newHandle, imageHandle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change to GC necessary? Is it a bug in the existing implementation?

Copy link
Contributor Author

@amartya4256 amartya4256 Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this method is created from the earlier implementation of the PlainImageDataProvider as in case it uses GC to scale, it uses this specific method. In the init method of GC, it uses the Image.win32_getHandle, which would want to create a handle and since we already are in the middle of creation of the handle it will fail. Since we also had a specific method in the past for this case, the idea is to use the ImageHandle we just obtained and pass that directly instead of calling win32_getHandle.

@amartya4256 amartya4256 force-pushed the amartya4256/image_concurrency_fix branch 2 times, most recently from e9cb651 to 0e6ad0d Compare December 30, 2025 15:56
@github-actions
Copy link
Contributor

github-actions bot commented Dec 30, 2025

Test Results (win32)

   34 files  ±0     34 suites  ±0   5m 26s ⏱️ + 1m 9s
4 628 tests ±0  4 555 ✅ ±0  73 💤 ±0  0 ❌ ±0 
  167 runs  ±0    164 ✅ ±0   3 💤 ±0  0 ❌ ±0 

Results for commit 22f6ab7. ± Comparison against base commit 383ed2a.

♻️ This comment has been updated with latest results.

@amartya4256 amartya4256 marked this pull request as ready for review January 2, 2026 14:45
@amartya4256 amartya4256 force-pushed the amartya4256/image_concurrency_fix branch from 0e6ad0d to 1494ed0 Compare January 2, 2026 15:27
amartya4256 and others added 2 commits January 2, 2026 16:33
This commit adds a class ImageHandleManager in Image to manage
multiple ImageHandle for different zoom hence encapsulating the usages
and operations based on zoomLevelToImageHandle.
This commit makes the ImageHandle creation and ImageData caching process
synchronous to avoid any racing condition and inefficient memory usages.
@amartya4256 amartya4256 force-pushed the amartya4256/image_concurrency_fix branch from 1494ed0 to 22f6ab7 Compare January 2, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make Image class thread safe

2 participants