Skip to content

Commit deef9de

Browse files
authored
Merge pull request processing#4862 from jdf/master
Fix a number of memory leaks.
2 parents 4de17ed + c01d88b commit deef9de

4 files changed

Lines changed: 119 additions & 156 deletions

File tree

core/src/processing/core/PApplet.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,6 +3634,18 @@ public void dispose() {
36343634
// run dispose() methods registered by libraries
36353635
handleMethods("dispose");
36363636
}
3637+
3638+
if (platform == MACOSX) {
3639+
try {
3640+
final String td = "processing.core.ThinkDifferent";
3641+
final Class<?> thinkDifferent =
3642+
Thread.currentThread().getContextClassLoader().loadClass(td);
3643+
thinkDifferent.getMethod("cleanup").invoke(null);
3644+
} catch (Exception e) {
3645+
e.printStackTrace();
3646+
}
3647+
}
3648+
36373649
}
36383650

36393651

core/src/processing/core/ThinkDifferent.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ public void handleQuitRequestWith(QuitEvent event, QuitResponse response) {
7171
});
7272
}
7373

74+
static public void cleanup() {
75+
if (application == null) {
76+
application = Application.getApplication();
77+
}
78+
application.setQuitHandler(null);
79+
}
7480

7581
// Called via reflection from PSurfaceAWT and others
7682
static public void setIconImage(Image image) {

core/src/processing/opengl/PGraphicsOpenGL.java

Lines changed: 68 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,44 @@ public class PGraphicsOpenGL extends PGraphics {
4949

5050
// ........................................................
5151

52+
// Disposal of native resources
53+
// Using the technique alternative to finalization described in:
54+
// http://www.oracle.com/technetwork/articles/java/finalization-137655.html
55+
private static ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
56+
private static List<Disposable<? extends Object>> reachableWeakReferences =
57+
new LinkedList<>();
58+
59+
static final private int MAX_DRAIN_GLRES_ITERATIONS = 10;
60+
61+
static void drainRefQueueBounded() {
62+
int iterations = 0;
63+
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
64+
Disposable<? extends Object> res =
65+
(Disposable<? extends Object>) refQueue.poll();
66+
if (res == null) {
67+
break;
68+
}
69+
res.dispose();
70+
++iterations;
71+
}
72+
}
73+
74+
private static abstract class Disposable<T> extends WeakReference<T> {
75+
protected Disposable(T obj) {
76+
super(obj, refQueue);
77+
drainRefQueueBounded();
78+
reachableWeakReferences.add(this);
79+
}
80+
81+
public void dispose() {
82+
System.err.println("disposing " + this );
83+
reachableWeakReferences.remove(this);
84+
disposeNative();
85+
}
86+
87+
abstract public void disposeNative();
88+
}
89+
5290
// Basic rendering parameters:
5391

5492
/** Whether the PGraphics object is ready to render or not. */
@@ -820,54 +858,27 @@ protected void removeFontTexture(PFont font) {
820858

821859
//////////////////////////////////////////////////////////////
822860

823-
// RESOURCE HANDLING
824-
// Using the technique alternative to finalization described in:
825-
// http://www.oracle.com/technetwork/articles/java/finalization-137655.html
826-
827-
static final private int MAX_DRAIN_GLRES_ITERATIONS = 10;
828861

829-
protected static class GLResourceTexture extends WeakReference<Texture> {
862+
protected static class GLResourceTexture extends Disposable<Texture> {
830863
int glName;
831864

832865
private PGL pgl;
833866
private int context;
834867

835-
static private ReferenceQueue<Texture> refQueue = new ReferenceQueue<Texture>();
836-
static private List<GLResourceTexture> refList = new ArrayList<GLResourceTexture>();
837-
838-
static void drainRefQueueBounded() {
839-
ReferenceQueue<Texture> refQueue = GLResourceTexture.referenceQueue();
840-
int iterations = 0;
841-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
842-
GLResourceTexture res = (GLResourceTexture)refQueue.poll();
843-
if (res == null) {
844-
break;
845-
}
846-
res.dispose();
847-
++iterations;
848-
}
849-
}
850-
851-
static ReferenceQueue<Texture> referenceQueue() {
852-
return refQueue;
853-
}
854-
855868
public GLResourceTexture(Texture tex) {
856-
super(tex, refQueue);
869+
super(tex);
857870

858-
drainRefQueueBounded();
859871

860872
pgl = tex.pg.getPrimaryPGL();
861873
pgl.genTextures(1, intBuffer);
862874
tex.glName = intBuffer.get(0);
863875

864876
this.glName = tex.glName;
865877
this.context = tex.context;
866-
867-
refList.add(this);
868878
}
869879

870-
private void disposeNative() {
880+
@Override
881+
public void disposeNative() {
871882
if (pgl != null) {
872883
if (glName != 0) {
873884
intBuffer.put(0, glName);
@@ -878,13 +889,11 @@ private void disposeNative() {
878889
}
879890
}
880891

881-
void dispose() {
882-
refList.remove(this);
883-
disposeNative();
884-
}
885-
886892
@Override
887893
public boolean equals(Object obj) {
894+
if (!(obj instanceof GLResourceTexture)) {
895+
return false;
896+
}
888897
GLResourceTexture other = (GLResourceTexture)obj;
889898
return other.glName == glName &&
890899
other.context == context;
@@ -900,48 +909,25 @@ public int hashCode() {
900909
}
901910

902911

903-
protected static class GLResourceVertexBuffer extends WeakReference<VertexBuffer> {
912+
protected static class GLResourceVertexBuffer extends Disposable<VertexBuffer> {
904913
int glId;
905914

906915
private PGL pgl;
907916
private int context;
908917

909-
static private ReferenceQueue<VertexBuffer> refQueue = new ReferenceQueue<VertexBuffer>();
910-
static private List<GLResourceVertexBuffer> refList = new ArrayList<GLResourceVertexBuffer>();
911-
912-
static void drainRefQueueBounded() {
913-
ReferenceQueue<VertexBuffer> refQueue = GLResourceVertexBuffer.referenceQueue();
914-
int iterations = 0;
915-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
916-
GLResourceVertexBuffer res = (GLResourceVertexBuffer)refQueue.poll();
917-
if (res == null) {
918-
break;
919-
}
920-
res.dispose();
921-
++iterations;
922-
}
923-
}
924-
925-
static ReferenceQueue<VertexBuffer> referenceQueue() {
926-
return refQueue;
927-
}
928-
929918
public GLResourceVertexBuffer(VertexBuffer vbo) {
930-
super(vbo, refQueue);
931-
932-
drainRefQueueBounded();
919+
super(vbo);
933920

934921
pgl = vbo.pgl.graphics.getPrimaryPGL();
935922
pgl.genBuffers(1, intBuffer);
936923
vbo.glId = intBuffer.get(0);
937924

938925
this.glId = vbo.glId;
939926
this.context = vbo.context;
940-
941-
refList.add(this);
942927
}
943928

944-
private void disposeNative() {
929+
@Override
930+
public void disposeNative() {
945931
if (pgl != null) {
946932
if (glId != 0) {
947933
intBuffer.put(0, glId);
@@ -952,13 +938,11 @@ private void disposeNative() {
952938
}
953939
}
954940

955-
void dispose() {
956-
refList.remove(this);
957-
disposeNative();
958-
}
959-
960941
@Override
961942
public boolean equals(Object obj) {
943+
if (!(obj instanceof GLResourceVertexBuffer)) {
944+
return false;
945+
}
962946
GLResourceVertexBuffer other = (GLResourceVertexBuffer)obj;
963947
return other.glId == glId &&
964948
other.context == context;
@@ -974,38 +958,16 @@ public int hashCode() {
974958
}
975959

976960

977-
protected static class GLResourceShader extends WeakReference<PShader> {
961+
protected static class GLResourceShader extends Disposable<PShader> {
978962
int glProgram;
979963
int glVertex;
980964
int glFragment;
981965

982966
private PGL pgl;
983967
private int context;
984968

985-
static private ReferenceQueue<PShader> refQueue = new ReferenceQueue<PShader>();
986-
static private List<GLResourceShader> refList = new ArrayList<GLResourceShader>();
987-
988-
static void drainRefQueueBounded() {
989-
ReferenceQueue<PShader> refQueue = GLResourceShader.referenceQueue();
990-
int iterations = 0;
991-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
992-
GLResourceShader res = (GLResourceShader)refQueue.poll();
993-
if (res == null) {
994-
break;
995-
}
996-
res.dispose();
997-
++iterations;
998-
}
999-
}
1000-
1001-
static ReferenceQueue<PShader> referenceQueue() {
1002-
return refQueue;
1003-
}
1004-
1005969
public GLResourceShader(PShader sh) {
1006-
super(sh, refQueue);
1007-
1008-
drainRefQueueBounded();
970+
super(sh);
1009971

1010972
this.pgl = sh.pgl.graphics.getPrimaryPGL();
1011973
sh.glProgram = pgl.createProgram();
@@ -1017,11 +979,10 @@ public GLResourceShader(PShader sh) {
1017979
this.glFragment = sh.glFragment;
1018980

1019981
this.context = sh.context;
1020-
1021-
refList.add(this);
1022982
}
1023983

1024-
private void disposeNative() {
984+
@Override
985+
public void disposeNative() {
1025986
if (pgl != null) {
1026987
if (glFragment != 0) {
1027988
pgl.deleteShader(glFragment);
@@ -1039,13 +1000,11 @@ private void disposeNative() {
10391000
}
10401001
}
10411002

1042-
void dispose() {
1043-
refList.remove(this);
1044-
disposeNative();
1045-
}
1046-
10471003
@Override
10481004
public boolean equals(Object obj) {
1005+
if (!(obj instanceof GLResourceShader)) {
1006+
return false;
1007+
}
10491008
GLResourceShader other = (GLResourceShader)obj;
10501009
return other.glProgram == glProgram &&
10511010
other.glVertex == glVertex &&
@@ -1065,7 +1024,7 @@ public int hashCode() {
10651024
}
10661025

10671026

1068-
protected static class GLResourceFrameBuffer extends WeakReference<FrameBuffer> {
1027+
protected static class GLResourceFrameBuffer extends Disposable<FrameBuffer> {
10691028
int glFbo;
10701029
int glDepth;
10711030
int glStencil;
@@ -1075,30 +1034,8 @@ protected static class GLResourceFrameBuffer extends WeakReference<FrameBuffer>
10751034
private PGL pgl;
10761035
private int context;
10771036

1078-
static private ReferenceQueue<FrameBuffer> refQueue = new ReferenceQueue<FrameBuffer>();
1079-
static private List<GLResourceFrameBuffer> refList = new ArrayList<GLResourceFrameBuffer>();
1080-
1081-
static void drainRefQueueBounded() {
1082-
ReferenceQueue<FrameBuffer> refQueue = GLResourceFrameBuffer.referenceQueue();
1083-
int iterations = 0;
1084-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
1085-
GLResourceFrameBuffer res = (GLResourceFrameBuffer)refQueue.poll();
1086-
if (res == null) {
1087-
break;
1088-
}
1089-
res.dispose();
1090-
++iterations;
1091-
}
1092-
}
1093-
1094-
static ReferenceQueue<FrameBuffer> referenceQueue() {
1095-
return refQueue;
1096-
}
1097-
10981037
public GLResourceFrameBuffer(FrameBuffer fb) {
1099-
super(fb, refQueue);
1100-
1101-
drainRefQueueBounded();
1038+
super(fb);
11021039

11031040
pgl = fb.pg.getPrimaryPGL();
11041041
if (!fb.screenFb) {
@@ -1132,11 +1069,10 @@ public GLResourceFrameBuffer(FrameBuffer fb) {
11321069
}
11331070

11341071
this.context = fb.context;
1135-
1136-
refList.add(this);
11371072
}
11381073

1139-
private void disposeNative() {
1074+
@Override
1075+
public void disposeNative() {
11401076
if (pgl != null) {
11411077
if (glFbo != 0) {
11421078
intBuffer.put(0, glFbo);
@@ -1167,13 +1103,11 @@ private void disposeNative() {
11671103
}
11681104
}
11691105

1170-
void dispose() {
1171-
refList.remove(this);
1172-
disposeNative();
1173-
}
1174-
11751106
@Override
11761107
public boolean equals(Object obj) {
1108+
if (!(obj instanceof GLResourceFrameBuffer)) {
1109+
return false;
1110+
}
11771111
GLResourceFrameBuffer other = (GLResourceFrameBuffer)obj;
11781112
return other.glFbo == glFbo &&
11791113
other.glDepth == glDepth &&
@@ -6586,6 +6520,8 @@ protected void deleteSurfaceTextures() {
65866520
if (filterTexture != null) {
65876521
filterTexture.dispose();
65886522
}
6523+
6524+
65896525
}
65906526

65916527

0 commit comments

Comments
 (0)