Bug 335745 - Draw2d should support use from multiple threads
Summary: Draw2d should support use from multiple threads
Status: NEW
Alias: None
Product: GEF
Classification: Tools
Component: GEF-Legacy Draw2d (show other bugs)
Version: unspecified   Edit
Hardware: PC All
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: gef-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-01-28 17:56 EST by Randy Hudson CLA
Modified: 2011-01-28 17:56 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Randy Hudson CLA 2011-01-28 17:56:59 EST
It's a common misconception that SWT can only be used from a Display thread (even if this were true, on some platform you can construct more than one Display).  The Display-thread limitation is true for SWT's Widgets, but the limitation does not apply to Images, GCs, Fonts, Colors, Patterns, Regions, Transforms, etc.  Draw2d/GEF are being used on servers to generate images for webpages.  They can also be used in rich client applications by background "worker" threads to generate thumbnails or other images.  Today, clients must use workarounds to guarantee proper results.  These workarounds include placing all calls to figure validation and painting inside a synchronized block.  When handling multiple requests from clients, the server is effectively single-threaded.

FWIW, ColorConstants was changed in the past to allow the class to be loaded by a background thread.

There are only a few remaining places to patch that would allow draw2d to safely be used in multiple threads.  Note that I'm not suggesting that *instances* of figures or anything else would be thread-safe.  The changes proposed here are the minimum required so that completely unrelated instances of figure, etc. can be validated and then painted onto images.

1) FigureUtilities changes:

protected static GC getGC() {
	if (gc == null) {
		gc = new GC(new Image(null, 1, 1));
		appliedFont = gc.getFont();
	}
	return gc;
}

Instead of creating a Shell, which must happen the first time on a Display thread, use an Image instead.  Images can be created on any thread.

getFontMetrics, getStringDimension, and getTextDimension all need to be made synchronized to guarantee exclusive access to the GC singleton.

2) Delete all occurrences of static Point and Rectangle instances (except for the ones which are not expected to ever change).  If they are currently API, @deprecate.  Fix all broken code to just use new instances.

- AbstractBorder#tempRect (becomes @deprecated)
- Figure#PRIVATE_RECT
- Figure#PRIVATE_POINT
- AbstractRouter#START
- AbstractRouter#END
- Rectangle#SINGLETON (becomes @deprecated)
- Point#SINGLETON (becomes @deprecated)
- Dimension#SINGLETON (becomes @deprecated)

3) [optional] If creating new geometry instances is really still a performance concern on modern JVMs, the biggest offender is probably in Figure#paintClientArea.  To avoid creating a new Rectangle there, just add a new method: Graphics#clipRect(int,int,int,int).