mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JRE-193 UI freeze and 12/second thread dumps
Moved CStrikeDisposer dispose code to AppKit
(cherry picked from commit 28774d6878)
This commit is contained in:
committed by
alexey.ushakov@jetbrains.com
parent
0b27afa493
commit
79d3896473
@@ -25,6 +25,8 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import sun.lwawt.macosx.concurrent.Dispatch;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.*;
|
||||
import java.util.HashMap;
|
||||
@@ -366,7 +368,7 @@ public final class CStrike extends PhysicalStrike {
|
||||
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
|
||||
|
||||
// rdar://problem/5204197
|
||||
private boolean disposed = false;
|
||||
private final AtomicBoolean disposed = new AtomicBoolean(false);
|
||||
|
||||
private final long[] firstLayerCache;
|
||||
private SparseBitShiftingTwoLayerArray secondLayerCache;
|
||||
@@ -429,41 +431,64 @@ public final class CStrike extends PhysicalStrike {
|
||||
}
|
||||
|
||||
public synchronized void dispose() {
|
||||
// rdar://problem/5204197
|
||||
// Note that sun.font.Font2D.getStrike() actively disposes
|
||||
// cleared strikeRef. We need to check the disposed flag to
|
||||
// prevent double frees of native resources.
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
final Runnable command = () -> {
|
||||
// rdar://problem/5204197
|
||||
// Note that sun.font.Font2D.getStrike() actively disposes
|
||||
// cleared strikeRef. We need to check the disposed flag to
|
||||
// prevent double frees of native resources.
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
|
||||
super.dispose();
|
||||
super.dispose();
|
||||
|
||||
// clean out the first array
|
||||
disposeLongArray(firstLayerCache);
|
||||
// clean out the first array
|
||||
disposeLongArray(firstLayerCache);
|
||||
|
||||
// clean out the two layer arrays
|
||||
if (secondLayerCache != null) {
|
||||
final long[][] secondLayerLongArrayArray = secondLayerCache.cache;
|
||||
for (int i = 0; i < secondLayerLongArrayArray.length; i++) {
|
||||
final long[] longArray = secondLayerLongArrayArray[i];
|
||||
if (longArray != null) disposeLongArray(longArray);
|
||||
}
|
||||
}
|
||||
// clean out the two layer arrays
|
||||
if (secondLayerCache != null) {
|
||||
final long[][] secondLayerLongArrayArray = secondLayerCache.cache;
|
||||
for (final long[] longArray : secondLayerLongArrayArray) {
|
||||
if (longArray != null) disposeLongArray(longArray);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up everyone else
|
||||
if (generalCache != null) {
|
||||
for (long longValue : generalCache.values()) {
|
||||
if (longValue != -1 && longValue != 0) {
|
||||
removeGlyphInfoFromCache(longValue);
|
||||
StrikeCache.freeLongPointer(longValue);
|
||||
// clean up everyone else
|
||||
if (generalCache != null) {
|
||||
for (long longValue : generalCache.values()) {
|
||||
if (longValue != -1 && longValue != 0) {
|
||||
removeGlyphInfoFromCache(longValue);
|
||||
StrikeCache.freeLongPointer(longValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (generalCache != null) {
|
||||
for (Long aLong : generalCache.values()) {
|
||||
final long longValue = aLong;
|
||||
if (longValue != -1 && longValue != 0) {
|
||||
removeGlyphInfoFromCache(longValue);
|
||||
StrikeCache.freeLongPointer(longValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// rdar://problem/5204197
|
||||
// Finally, set the flag.
|
||||
disposed = true;
|
||||
// Move disposal code to AppKit thread in order to avoid the
|
||||
// following deadlock:
|
||||
// 1) CGLGraphicsConfig.getCGLConfigInfo (called from Java2D
|
||||
// disposal thread) takes RenderQueue.lock
|
||||
// 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
|
||||
// blocked on RenderQueue.lock
|
||||
// 1) invokes native block on AppKit and wait
|
||||
//
|
||||
// If dispatch instance is not available, run the code on
|
||||
// disposal thread as before
|
||||
|
||||
final Dispatch dispatch = Dispatch.getInstance();
|
||||
|
||||
if (!CThreading.isAppKit() && dispatch != null)
|
||||
dispatch.getNonBlockingMainQueueExecutor().execute(command);
|
||||
else
|
||||
command.run();
|
||||
}
|
||||
|
||||
private static void disposeLongArray(final long[] longArray) {
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
|
||||
package sun.font;
|
||||
|
||||
import sun.lwawt.macosx.concurrent.Dispatch;
|
||||
import sun.lwawt.macosx.CThreading;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/*
|
||||
* This keeps track of data that needs to be cleaned up once a
|
||||
* strike is freed.
|
||||
@@ -49,6 +54,7 @@ package sun.font;
|
||||
class CStrikeDisposer extends FontStrikeDisposer {
|
||||
|
||||
long pNativeScalerContext;
|
||||
private final AtomicBoolean disposed = new AtomicBoolean(false);
|
||||
|
||||
public CStrikeDisposer(Font2D font2D, FontStrikeDesc desc,
|
||||
long pContext, int[] images)
|
||||
@@ -76,12 +82,31 @@ class CStrikeDisposer extends FontStrikeDisposer {
|
||||
}
|
||||
|
||||
public synchronized void dispose() {
|
||||
if (!disposed) {
|
||||
if (pNativeScalerContext != 0L) {
|
||||
freeNativeScalerContext(pNativeScalerContext);
|
||||
final Runnable command = () -> {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
if (pNativeScalerContext != 0L) {
|
||||
freeNativeScalerContext(pNativeScalerContext);
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
};
|
||||
// Move disposal code to AppKit thread in order to avoid the
|
||||
// following deadlock:
|
||||
// 1) CGLGraphicsConfig.getCGLConfigInfo (called from Java2D
|
||||
// disposal thread) takes RenderQueue.lock
|
||||
// 2) CGLLayer.drawInCGLContext is invoked on AppKit thread and
|
||||
// blocked on RenderQueue.lock
|
||||
// 1) invokes native block on AppKit and wait
|
||||
//
|
||||
// If dispatch instance is not available, run the code on
|
||||
// disposal thread as before
|
||||
|
||||
final Dispatch dispatch = Dispatch.getInstance();
|
||||
|
||||
if (!CThreading.isAppKit() && dispatch != null)
|
||||
dispatch.getNonBlockingMainQueueExecutor().execute(command);
|
||||
else
|
||||
command.run();
|
||||
}
|
||||
|
||||
private native void freeNativeScalerContext(long pContext);
|
||||
|
||||
Reference in New Issue
Block a user