Add Thread.interrupt support

This commit is contained in:
Alexey Andreev 2015-06-20 19:19:50 +03:00
parent e59351723a
commit 5b5f4fd176
4 changed files with 117 additions and 13 deletions

View File

@ -267,7 +267,8 @@ public class TObject {
monitorExit(this, monitor.count);
}
private static class NotifyListenerImpl implements NotifyListener, TimerHandler, PlatformRunnable {
private static class NotifyListenerImpl implements NotifyListener, TimerHandler, PlatformRunnable,
TThreadInterruptHandler {
final TObject obj;
final AsyncCallback<Void> callback;
final TThread currentThread = TThread.currentThread();
@ -309,6 +310,23 @@ public class TObject {
TThread.setCurrentThread(currentThread);
monitorEnterWait(obj, lockCount, callback);
}
@Override
public void interrupted() {
if (performed) {
return;
}
performed = true;
if (timerId >= 0) {
Platform.killSchedule(timerId);
timerId = -1;
}
Platform.postpone(new PlatformRunnable() {
@Override public void run() {
callback.error(new TInterruptedException());
}
});
}
}
@Rename("wait")

View File

@ -37,8 +37,9 @@ public class TThread extends TObject implements TRunnable {
private long timeSliceStart;
private int yieldCount;
private final Object finishedLock = new Object();
private boolean interruptedFlag;
private TThreadInterruptHandler interruptHandler;
private TString name;
TRunnable target;
@ -104,20 +105,20 @@ public class TThread extends TObject implements TRunnable {
public TString getName() {
return name;
}
public final void join(long millis, int nanos) throws InterruptedException {
if (currentThread() == this) {
return;
}
synchronized(finishedLock) {
synchronized (finishedLock) {
finishedLock.wait(millis, nanos);
}
}
public final void join(long millis) throws InterruptedException {
join(millis, 0);
}
public final void join() throws InterruptedException {
join(0);
}
@ -146,14 +147,22 @@ public class TThread extends TObject implements TRunnable {
}
public void interrupt() {
interruptedFlag = true;
if (interruptHandler != null) {
interruptHandler.interrupted();
interruptHandler = null;
}
}
public static boolean interrupted() {
return false;
TThread thread = currentThread();
boolean result = thread.interruptedFlag;
thread.interruptedFlag = false;
return result;
}
public boolean isInterrupted() {
return false;
return interruptedFlag;
}
public static int activeCount() {
@ -174,12 +183,42 @@ public class TThread extends TObject implements TRunnable {
private static void sleep(long millis, final AsyncCallback<Void> callback) {
final TThread current = currentThread();
int intMillis = millis < Integer.MAX_VALUE ? (int)millis : Integer.MAX_VALUE;
Platform.schedule(new PlatformRunnable() {
@Override public void run() {
setCurrentThread(current);
SleepHandler handler = new SleepHandler(current, callback);
handler.scheduleId = Platform.schedule(handler, intMillis);
current.interruptHandler = handler;
}
private static class SleepHandler implements PlatformRunnable, TThreadInterruptHandler {
private TThread thread;
private AsyncCallback<Void> callback;
private boolean isInterrupted;
int scheduleId;
public SleepHandler(TThread thread, AsyncCallback<Void> callback) {
this.thread = thread;
this.callback = callback;
}
@Override
public void interrupted() {
thread.interruptedFlag = false;
isInterrupted = true;
Platform.killSchedule(scheduleId);
Platform.postpone(new PlatformRunnable() {
@Override public void run() {
callback.error(new TInterruptedException());
}
});
}
@Override
public void run() {
if (!isInterrupted) {
thread.interruptHandler = null;
setCurrentThread(thread);
callback.complete(null);
}
}, intMillis);
}
}
public final void setPriority(int newPriority){

View File

@ -0,0 +1,24 @@
/*
* Copyright 2015 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang;
/**
*
* @author Alexey Andreev
*/
public interface TThreadInterruptHandler {
void interrupted();
}

View File

@ -33,6 +33,29 @@ public class ThreadTest {
assertTrue("Thread.sleed did not wait enogh", duration >= 100);
}
@Test
public void sleepInterrupted() {
long start = System.currentTimeMillis();
final Thread mainThread = Thread.currentThread();
new Thread() {
@Override public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
mainThread.interrupt();
}
}.start();
try {
Thread.sleep(300);
fail("Exception expected");
} catch (InterruptedException e) {
assertEquals(Thread.currentThread(), mainThread);
assertFalse(mainThread.isInterrupted());
assertTrue(System.currentTimeMillis() - start < 150);
}
}
@Test
public void catchesAsyncException() {
try {