Skip to content

Conversation

@amartya4256
Copy link
Contributor

@amartya4256 amartya4256 commented Dec 22, 2025

This PR handles the creation of handles / cached ImageData per zoom for Image objects in a thread-safe way by the means of double-checked locking. The implementation extends the ImageHandleManager in the following way:

  • ImageHandleManager#getHandleOrCreate now uses double-checked locking for thread-safety
  • ImageHandleManager provides a method runSynchronized for to run a block of code synchronously. This is utilized while calling getImageData to ensure thread safety.

Depends on #2927
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
@amartya4256 amartya4256 changed the title Using ImageHandleManager for managing multiple Image handles in Image class Implemented Double-Checked Locking in ImagehandleManager Jan 5, 2026
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