diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 2d321193a0..4846287daf 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -139,9 +139,17 @@ public class Thread implements Runnable { public static native Thread currentThread(); - public native void interrupt(); + public void interrupt() { + interrupt(peer); + } - public native boolean interrupted(); + private static native boolean interrupt(long peer); + + public boolean interrupted() { + return interrupted(peer); + } + + private static native boolean interrupted(long peer); public static boolean isInterrupted() { return currentThread().interrupted; diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 89c6cdc13d..7d3459307b 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -554,6 +554,15 @@ Avian_java_lang_Thread_interrupt interrupt(t, reinterpret_cast(peer)); } +extern "C" JNIEXPORT int64_t JNICALL +Avian_java_lang_Thread_interrupted +(Thread* t, object, uintptr_t* arguments) +{ + int64_t peer; memcpy(&peer, arguments, 8); + + return getAndClearInterrupted(t, reinterpret_cast(peer)); +} + extern "C" JNIEXPORT int64_t JNICALL Avian_java_lang_Thread_getStackTrace (Thread* t, object, uintptr_t* arguments) diff --git a/src/machine.h b/src/machine.h index 2a69b8e038..5ed0bb104c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -3236,6 +3236,18 @@ interrupt(Thread* t, Thread* target) } } +inline bool +getAndClearInterrupted(Thread* t, Thread* target) +{ + if (acquireSystem(t, target)) { + bool result = target->systemThread->getAndClearInterrupted(); + releaseSystem(t, target); + return result; + } else { + return false; + } +} + object intern(Thread* t, object s); diff --git a/src/posix.cpp b/src/posix.cpp index 2a5c7daf78..59d2fb08f0 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -151,6 +151,16 @@ class MySystem: public System { expect(s, rv == 0); } + virtual bool getAndClearInterrupted() { + ACQUIRE(mutex); + + bool interrupted = r->interrupted(); + + r->setInterrupted(false); + + return interrupted; + } + virtual void join() { int rv UNUSED = pthread_join(thread, 0); expect(s, rv == 0); diff --git a/src/system.h b/src/system.h index 6e2ea14721..25ec0bd455 100644 --- a/src/system.h +++ b/src/system.h @@ -29,6 +29,7 @@ class System { class Thread { public: virtual void interrupt() = 0; + virtual bool getAndClearInterrupted() = 0; virtual void join() = 0; virtual void dispose() = 0; }; diff --git a/src/windows.cpp b/src/windows.cpp index 4c75b80870..75591d614c 100644 --- a/src/windows.cpp +++ b/src/windows.cpp @@ -100,6 +100,16 @@ class MySystem: public System { } } + virtual bool getAndClearInterrupted() { + ACQUIRE(s, mutex); + + bool interrupted = r->interrupted(); + + r->setInterrupted(false); + + return interrupted; + } + virtual void join() { int r UNUSED = WaitForSingleObject(thread, INFINITE); assert(s, r == WAIT_OBJECT_0); diff --git a/test/Threads.java b/test/Threads.java index c411c8c61c..a6292e74fb 100644 --- a/test/Threads.java +++ b/test/Threads.java @@ -1,15 +1,36 @@ public class Threads implements Runnable { public static void main(String[] args) { - Threads test = new Threads(); - Thread thread = new Thread(test); + { Threads test = new Threads(); + Thread thread = new Thread(test); - try { - synchronized (test) { - thread.start(); - test.wait(); + try { + synchronized (test) { + thread.start(); + test.wait(); + } + } catch (Throwable e) { + e.printStackTrace(); } - } catch (Throwable e) { - e.printStackTrace(); + } + + { Thread thread = new Thread() { + public void run() { + while (true) { + System.out.print("."); + try { + sleep(1000); + } catch (Exception e) { + System.out.println("thread interrupted? " + interrupted()); + break; + } + } + } + }; + thread.start(); + + System.out.println("\nAbout to interrupt..."); + thread.interrupt(); + System.out.println("\nInterrupted!"); } System.out.println("finished");