8037840: [macosx] Rewrite CWarning window to eliminate the ExecutorService
Reviewed-by: anthony, serb
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Thu Mar 20 12:10:53 2014 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Thu Mar 20 16:58:58 2014 +0400
@@ -27,7 +27,6 @@
import sun.awt.AWTAccessor;
import sun.awt.IconInfo;
-import sun.awt.SunToolkit;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.java2d.opengl.CGLLayer;
@@ -39,17 +38,11 @@
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.lang.ref.WeakReference;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
public final class CWarningWindow extends CPlatformWindow
implements SecurityWarningWindow, PlatformEventNotifier {
- private static class Lock {};
+ private static class Lock {}
private final Lock lock = new Lock();
private final static int SHOWING_DELAY = 300;
@@ -97,7 +90,7 @@
public CWarningWindow(final Window _ownerWindow, final LWWindowPeer _ownerPeer) {
super();
- this.ownerPeer = new WeakReference<LWWindowPeer>(_ownerPeer);
+ this.ownerPeer = new WeakReference<>(_ownerPeer);
this.ownerWindow = _ownerWindow;
initialize(null, null, _ownerPeer.getPlatformWindow());
@@ -122,16 +115,8 @@
}
public void setVisible(boolean visible, boolean doSchedule) {
- synchronized (scheduler) {
- if (showingTaskHandle != null) {
- showingTaskHandle.cancel(false);
- showingTaskHandle = null;
- }
-
- if (hidingTaskHandle != null) {
- hidingTaskHandle.cancel(false);
- hidingTaskHandle = null;
- }
+ synchronized (taskLock) {
+ cancelTasks();
if (visible) {
if (isVisible()) {
@@ -140,20 +125,18 @@
currentIcon = 2;
}
- showingTaskHandle = scheduler.schedule(showingTask, 50,
- TimeUnit.MILLISECONDS);
-
+ showHideTask = new ShowingTask();
+ LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50);
} else {
if (!isVisible()) {
return;
}
+ showHideTask = new HidingTask();
if (doSchedule) {
- hidingTaskHandle = scheduler.schedule(hidingTask, HIDING_DELAY,
- TimeUnit.MILLISECONDS);
+ LWCToolkit.performOnMainThreadAfterDelay(showHideTask, HIDING_DELAY);
} else {
- hidingTaskHandle = scheduler.schedule(hidingTask, 50,
- TimeUnit.MILLISECONDS);
+ LWCToolkit.performOnMainThreadAfterDelay(showHideTask, 50);
}
}
}
@@ -325,13 +308,19 @@
@Override
public void dispose() {
- AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
- scheduler.shutdown();
- return null;
- });
+ cancelTasks();
super.dispose();
}
+ private void cancelTasks() {
+ synchronized (taskLock) {
+ if (showHideTask != null) {
+ showHideTask.cancel();
+ showHideTask = null;
+ }
+ }
+ }
+
private void updateIconSize() {
int newSize = -1;
@@ -364,7 +353,7 @@
}
}
- private final Graphics getGraphics() {
+ private Graphics getGraphics() {
SurfaceData sd = contentView.getSurfaceData();
if (ownerWindow == null || sd == null) {
return null;
@@ -409,44 +398,59 @@
return getSecurityIconInfo(currentSize, currentIcon);
}
- private final Runnable hidingTask = new Runnable() {
- public void run() {
+ private final Lock taskLock = new Lock();
+ private CancelableRunnable showHideTask;
+
+ private static abstract class CancelableRunnable implements Runnable {
+ private volatile boolean perform = true;
+
+ public final void cancel() {
+ perform = false;
+ }
+
+ @Override
+ public final void run() {
+ if (perform) {
+ perform();
+ }
+ }
+
+ public abstract void perform();
+ }
+
+ private class HidingTask extends CancelableRunnable {
+ @Override
+ public void perform() {
synchronized (lock) {
setVisible(false);
}
- synchronized (scheduler) {
- hidingTaskHandle = null;
+ synchronized (taskLock) {
+ showHideTask = null;
}
}
- };
+ }
- private final Runnable showingTask = new Runnable() {
- public void run() {
+ private class ShowingTask extends CancelableRunnable {
+ @Override
+ public void perform() {
synchronized (lock) {
if (!isVisible()) {
setVisible(true);
}
-
repaint();
}
- synchronized (scheduler) {
+ synchronized (taskLock) {
if (currentIcon > 0) {
currentIcon--;
- showingTaskHandle = scheduler.schedule(showingTask, SHOWING_DELAY,
- TimeUnit.MILLISECONDS);
+ showHideTask = new ShowingTask();
+ LWCToolkit.performOnMainThreadAfterDelay(showHideTask, SHOWING_DELAY);
} else {
- showingTaskHandle = null;
+ showHideTask = null;
}
}
}
- };
-
- private final ScheduledExecutorService scheduler =
- Executors.newSingleThreadScheduledExecutor();
-
- private ScheduledFuture hidingTaskHandle;
- private ScheduledFuture showingTaskHandle;
+ }
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Mar 20 12:10:53 2014 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Mar 20 16:58:58 2014 +0400
@@ -47,7 +47,6 @@
import sun.lwawt.*;
import sun.lwawt.LWWindowPeer.PeerType;
import sun.security.action.GetBooleanAction;
-import sun.awt.image.MultiResolutionImage;
import sun.util.CoreResourceBundleControl;
@@ -671,6 +670,13 @@
throw new InvocationTargetException(eventException);
}
+ /**
+ * Schedules a {@code Runnable} execution on the Appkit thread after a delay
+ * @param r a {@code Runnable} to execute
+ * @param delay a delay in milliseconds
+ */
+ native static void performOnMainThreadAfterDelay(Runnable r, long delay);
+
// This exists purely to get around permissions issues with getSystemEventQueueImpl
EventQueue getSystemEventQueueForInvokeAndWait() {
return getSystemEventQueueImpl();
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Mar 20 12:10:53 2014 +0400
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Mar 20 16:58:58 2014 +0400
@@ -82,6 +82,39 @@
@end
+@interface JavaRunnable : NSObject { }
+@property jobject runnable;
+- (id)initWithRunnable:(jobject)gRunnable;
+- (void)perform;
+@end
+
+@implementation JavaRunnable
+@synthesize runnable = _runnable;
+
+- (id)initWithRunnable:(jobject)gRunnable {
+ if (self = [super init]) {
+ self.runnable = gRunnable;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ JNIEnv *env = [ThreadUtilities getJNIEnv];
+ if (self.runnable) {
+ (*env)->DeleteGlobalRef(env, self.runnable);
+ }
+ [super dealloc];
+}
+
+- (void)perform {
+ JNIEnv* env = [ThreadUtilities getJNIEnv];
+ static JNF_CLASS_CACHE(sjc_Runnable, "java/lang/Runnable");
+ static JNF_MEMBER_CACHE(jm_Runnable_run, sjc_Runnable, "run", "()V");
+ JNFCallVoidMethod(env, self.runnable, jm_Runnable_run);
+ [self release];
+}
+@end
+
/*
* Class: sun_lwawt_macosx_LWCToolkit
* Method: nativeSyncQueue
@@ -359,6 +392,25 @@
/*
* Class: sun_lwawt_macosx_LWCToolkit
+ * Method: performOnMainThreadAfterDelay
+ * Signature: (Ljava/lang/Runnable;J)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAfterDelay
+(JNIEnv *env, jclass clz, jobject runnable, jlong delay)
+{
+JNF_COCOA_ENTER(env);
+ jobject gRunnable = (*env)->NewGlobalRef(env, runnable);
+ CHECK_NULL(gRunnable);
+ [ThreadUtilities performOnMainThreadWaiting:NO block:^() {
+ JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable];
+ [performer performSelector:@selector(perform) withObject:nil afterDelay:(delay/1000.0)];
+ }];
+JNF_COCOA_EXIT(env);
+}
+
+
+/*
+ * Class: sun_lwawt_macosx_LWCToolkit
* Method: isCapsLockOn
* Signature: ()Z
*/
@@ -433,4 +485,3 @@
{
}
-