Skip to content

Commit

Permalink
Destroy unused handles od resources
Browse files Browse the repository at this point in the history
This Contribution destroys those handles for the resources which were
created for zoom levels which no monitor has anymore. The process is
triggered on a DPI_CHANGED event.

contributes to #62 and #127
  • Loading branch information
amartya4256 committed Sep 27, 2024
1 parent 02e20d6 commit 99f22f7
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,9 @@ public boolean loadFont (String path) {
}

void new_Object (Object object) {
if (!tracking) {
return;
}
synchronized (trackingLock) {
for (int i=0; i<objects.length; i++) {
if (objects [i] == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*******************************************************************************/
package org.eclipse.swt.graphics;

import java.util.*;
import java.util.function.*;

import org.eclipse.swt.*;
Expand Down Expand Up @@ -123,6 +124,19 @@ public Resource() {
void destroy() {
}

/**
* This method is supposed to be overridden by those resources which contain
* multiple handles for different zoom levels. The method destroys handles of
* the resource for all the zoom levels expect for the those passed in the
* argument.
*
* @param zoomLevels The zoom levels for which the handles are supposed to be
* retained.
*/
void destroyHandlesExcept(Set<Integer> zoomLevels) {

}

/**
* Disposes of the operating system resources associated with
* this resource. Applications must dispose of all resources
Expand Down Expand Up @@ -158,7 +172,7 @@ void ignoreNonDisposed() {
}

void init() {
if (device.tracking) device.new_Object(this);
device.new_Object(this);
}

void initNonDisposeTracking() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,9 @@ long logProc (long log_domain, long log_level, long message, long user_data) {
}

void new_Object (Object object) {
if (!tracking) {
return;
}
synchronized (trackingLock) {
for (int i=0; i<objects.length; i++) {
if (objects [i] == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
package org.eclipse.swt.graphics;


import java.util.*;

import org.eclipse.swt.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gdip.*;
import org.eclipse.swt.internal.win32.*;
import org.eclipse.swt.widgets.*;

/**
* This class is the abstract superclass of all device objects,
Expand Down Expand Up @@ -117,6 +120,7 @@ public Device(DeviceData data) {
debug = data.debug;
tracking = data.tracking;
}
initializeObjects();
if (tracking) {
startTracking();
}
Expand Down Expand Up @@ -148,26 +152,25 @@ public void setTracking(boolean tracking) {
if (tracking == this.tracking) {
return;
}
this.tracking = tracking;
initializeObjects();
if (tracking) {
startTracking();
} else {
stopTracking();
}
}

private void startTracking() {
errors = new Error [128];
private void initializeObjects() {
objects = new Object [128];
trackingLock = new Object ();
}

private void startTracking() {
errors = new Error [128];
}

private void stopTracking() {
synchronized (trackingLock) {
objects = null;
errors = null;
trackingLock = null;
}
errors = null;
}


Expand Down Expand Up @@ -336,13 +339,13 @@ public void dispose () {

destroy ();
disposed = true;
if (tracking) {
synchronized (trackingLock) {
printErrors ();
objects = null;
synchronized (trackingLock) {
printErrors ();
objects = null;
if (tracking) {
errors = null;
trackingLock = null;
}
trackingLock = null;
}
}
}
Expand All @@ -353,7 +356,9 @@ void dispose_Object (Object object) {
for (int i=0; i<objects.length; i++) {
if (objects [i] == object) {
objects [i] = null;
errors [i] = null;
if(tracking) {
errors [i] = null;
}
return;
}
}
Expand Down Expand Up @@ -436,26 +441,27 @@ public DeviceData getDeviceData () {
DeviceData data = new DeviceData ();
data.debug = debug;
data.tracking = tracking;
if (tracking) {
synchronized (trackingLock) {
int count = 0, length = objects.length;
for (int i=0; i<length; i++) {
if (objects [i] != null) count++;
}
int index = 0;
data.objects = new Object [count];
synchronized (trackingLock) {
int count = 0, length = objects.length;
for (int i=0; i<length; i++) {
if (objects [i] != null) count++;
}
int index = 0;
data.objects = new Object [count];
if (tracking) {
data.errors = new Error [count];
for (int i=0; i<length; i++) {
if (objects [i] != null) {
data.objects [index] = objects [i];
} else {
data.errors = new Error [0];
}
for (int i=0; i<length; i++) {
if (objects [i] != null) {
data.objects [index] = objects [i];
if (tracking) {
data.errors [index] = errors [i];
index++;
}
index++;
}
}
} else {
data.objects = new Object [0];
data.errors = new Error [0];
}
return data;
}
Expand Down Expand Up @@ -820,26 +826,30 @@ void new_Object (Object object) {
for (int i=0; i<objects.length; i++) {
if (objects [i] == null) {
objects [i] = object;
errors [i] = new Error ();
if (tracking) {
errors [i] = new Error ();
}
return;
}
}
Object [] newObjects = new Object [objects.length + 128];
System.arraycopy (objects, 0, newObjects, 0, objects.length);
newObjects [objects.length] = object;
objects = newObjects;
Error [] newErrors = new Error [errors.length + 128];
System.arraycopy (errors, 0, newErrors, 0, errors.length);
newErrors [errors.length] = new Error ();
errors = newErrors;
if (tracking) {
Error [] newErrors = new Error [errors.length + 128];
System.arraycopy (errors, 0, newErrors, 0, errors.length);
newErrors [errors.length] = new Error ();
errors = newErrors;
}
}
}

void printErrors () {
if (!DEBUG) return;
if (tracking) {
synchronized (trackingLock) {
if (objects == null || errors == null) return;
if (objects == null && errors == null) return;
int objectCount = 0;
int colors = 0, cursors = 0, fonts = 0, gcs = 0, images = 0;
int paths = 0, patterns = 0, regions = 0, textLayouts = 0, transforms = 0;
Expand Down Expand Up @@ -874,8 +884,10 @@ void printErrors () {
string = string.substring (0, string.length () - 2);
System.err.println (string);
}
for (Error error : errors) {
if (error != null) error.printStackTrace (System.err);
if(tracking) {
for (Error error : errors) {
if (error != null) error.printStackTrace (System.err);
}
}
}
}
Expand Down Expand Up @@ -947,4 +959,22 @@ public void setWarnings (boolean warnings) {
protected int getDeviceZoom () {
return DPIUtil.mapDPIToZoom ( _getDPIx ());
}

/**
* Destroys the handles of all the resources in the resource tracker by
* identifying the zoom levels which is not valid for any monitor
*
* @noreference This method is not intended to be referenced by clients.
*/
public static void win32_destroyUnusedHandles(Display display) {
Set<Integer> availableZoomLevels = new HashSet<>();
for (Monitor monitor : display.getMonitors()) {
availableZoomLevels.add(DPIUtil.getZoomForAutoscaleProperty(monitor.getZoom()));
}
for (Object object: ((Device) display).objects) {
if (object instanceof Resource resource) {
resource.destroyHandlesExcept(availableZoomLevels);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1186,16 +1186,31 @@ void destroy () {

private void destroyHandle () {
for (Long handle : zoomLevelToHandle.values()) {
if (type == SWT.ICON) {
OS.DestroyIcon (handle);
} else {
OS.DeleteObject (handle);
}
destroyHandle(handle);
}
zoomLevelToHandle.clear();
handle = 0;
}

@Override
void destroyHandlesExcept(Set<Integer> zoomLevels) {
zoomLevelToHandle.entrySet().removeIf(entry -> {
if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != DPIUtil.getZoomForAutoscaleProperty(initialNativeZoom)) {
destroyHandle(entry.getValue());
return true;
}
return false;
});
}

private void destroyHandle(long handle) {
if (type == SWT.ICON) {
OS.DestroyIcon (handle);
} else {
OS.DeleteObject (handle);
}
}

/**
* Compares the argument to the receiver, and returns true
* if they represent the <em>same</em> object using a class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,17 @@ void destroy() {
zoomLevelToHandle.clear();
}

@Override
void destroyHandlesExcept(Set<Integer> zoomLevels) {
zoomLevelToHandle.entrySet().removeIf(entry -> {
if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) {
Gdip.GraphicsPath_delete(entry.getValue());
return true;
}
return false;
});
}

/**
* Replaces the first four elements in the parameter with values that
* describe the smallest rectangle that will completely contain the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,21 +260,7 @@ void setImageHandle(Image image, int zoom) {
@Override
void destroy() {
for (long handle: zoomLevelToHandle.values()) {
int type = Gdip.Brush_GetType(handle);
switch (type) {
case Gdip.BrushTypeSolidColor:
Gdip.SolidBrush_delete(handle);
break;
case Gdip.BrushTypeHatchFill:
Gdip.HatchBrush_delete(handle);
break;
case Gdip.BrushTypeLinearGradient:
Gdip.LinearGradientBrush_delete(handle);
break;
case Gdip.BrushTypeTextureFill:
Gdip.TextureBrush_delete(handle);
break;
}
destroyHandle(handle);
}
zoomLevelToHandle.clear();
if (bitmapDestructor != null) {
Expand All @@ -283,6 +269,35 @@ void destroy() {
}
}

@Override
void destroyHandlesExcept(Set<Integer> zoomLevels) {
zoomLevelToHandle.entrySet().removeIf(entry -> {
if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) {
destroyHandle(entry.getValue());
return true;
}
return false;
});
}

private void destroyHandle(long handle) {
int type = Gdip.Brush_GetType(handle);
switch (type) {
case Gdip.BrushTypeSolidColor:
Gdip.SolidBrush_delete(handle);
break;
case Gdip.BrushTypeHatchFill:
Gdip.HatchBrush_delete(handle);
break;
case Gdip.BrushTypeLinearGradient:
Gdip.LinearGradientBrush_delete(handle);
break;
case Gdip.BrushTypeTextureFill:
Gdip.TextureBrush_delete(handle);
break;
}
}

/**
* Returns <code>true</code> if the Pattern has been disposed,
* and <code>false</code> otherwise.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ void destroy () {
operations.clear();
}

@Override
void destroyHandlesExcept(Set<Integer> zoomLevels) {
zoomToHandle.entrySet().removeIf(entry -> {
if (!zoomLevels.contains(entry.getKey()) && entry.getKey() != initialZoom) {
OS.DeleteObject(entry.getValue());
return true;
}
return false;
});
}

/**
* Compares the argument to the receiver, and returns true
* if they represent the <em>same</em> object using a class
Expand Down
Loading

0 comments on commit 99f22f7

Please sign in to comment.