Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions vm/ByteCodeTranslator/src/cn1_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,7 @@ struct ThreadLocalData {
char* utf8Buffer;
int utf8BufferSize;
JAVA_BOOLEAN threadKilled; // we don't expect to see this in the GC
JAVA_BOOLEAN interrupted;
};

//#define BLOCK_FOR_GC() while(threadStateData->threadBlockedByGC) { usleep(500); }
Expand Down
35 changes: 35 additions & 0 deletions vm/ByteCodeTranslator/src/nativeMethods.m
Original file line number Diff line number Diff line change
Expand Up @@ -1090,6 +1090,7 @@ JAVA_INT java_lang_Object_hashCode___R_int(CODENAME_ONE_THREAD_STATE, JAVA_OBJEC
i->threadBlockedByGC = JAVA_FALSE;
i->threadActive = JAVA_FALSE;
i->threadKilled = JAVA_FALSE;
i->interrupted = JAVA_FALSE;

i->currentThreadObject = 0;

Expand Down Expand Up @@ -1461,6 +1462,40 @@ JAVA_LONG java_lang_Thread_getNativeThreadId___R_long(CODENAME_ONE_THREAD_STATE)
return currentThreadId();
}

JAVA_VOID java_lang_Thread_interrupt0__(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT me) {
lockCriticalSection();
for(int i=0; i<NUMBER_OF_SUPPORTED_THREADS; i++) {
struct ThreadLocalData* d = allThreads[i];
if(d && d->currentThreadObject == me) {
d->interrupted = JAVA_TRUE;
break;
}
}
unlockCriticalSection();
}

JAVA_BOOLEAN java_lang_Thread_isInterrupted___boolean_R_boolean(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT me, JAVA_BOOLEAN clear) {
JAVA_BOOLEAN ret = JAVA_FALSE;
// optimization: checking current thread
if(threadStateData->currentThreadObject == me) {
ret = threadStateData->interrupted;
if(clear) threadStateData->interrupted = JAVA_FALSE;
return ret;
}

lockCriticalSection();
for(int i=0; i<NUMBER_OF_SUPPORTED_THREADS; i++) {
struct ThreadLocalData* d = allThreads[i];
if(d && d->currentThreadObject == me) {
ret = d->interrupted;
if(clear) d->interrupted = JAVA_FALSE;
break;
}
}
unlockCriticalSection();
return ret;
}

JAVA_DOUBLE java_lang_StringToReal_parseDblImpl___java_lang_String_int_R_double(CODENAME_ONE_THREAD_STATE, JAVA_OBJECT s, JAVA_INT e) {
int length = java_lang_String_length___R_int(threadStateData, s);
JAVA_ARRAY arrayData = (JAVA_ARRAY)java_lang_String_toCharNoCopy___R_char_1ARRAY(threadStateData, s);
Expand Down
71 changes: 67 additions & 4 deletions vm/JavaAPI/src/java/lang/Thread.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,21 @@ public final int getPriority(){
* Interrupts this thread. In an implementation conforming to the CLDC Specification, this operation is not required to cancel or clean up any pending I/O operations that the thread may be waiting for.
*/
public void interrupt(){
interrupt0();
}

private native void interrupt0();

public static boolean interrupted() {
return currentThread().isInterrupted(true);
}

public boolean isInterrupted() {
return isInterrupted(false);
}

private native boolean isInterrupted(boolean clearInterrupted);

/**
* Tests if this thread is alive. A thread is alive if it has been started and has not yet died.
*/
Expand All @@ -135,12 +148,46 @@ public final boolean isAlive(){
* Waits for this thread to die.
*/
public final void join() throws java.lang.InterruptedException{
// not very efficient but we don't use this method much...
while(alive) {
sleep(30);
join(0);
}

public final synchronized void join(long millis) throws java.lang.InterruptedException {
long base = System.currentTimeMillis();
long now = 0;

if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

public final synchronized void join(long millis, int nanos) throws java.lang.InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException("nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
join(millis);
}

/**
* Invoked from native code...
*/
Expand All @@ -155,7 +202,10 @@ private void runImpl(long tid) {
t.printStackTrace();
}
activeThreads--;
alive = false;
synchronized(this) {
alive = false;
notifyAll();
}
}

/**
Expand Down Expand Up @@ -183,6 +233,19 @@ public final void setPriority(int newPriority){
*/
public static native void sleep(long millis) throws java.lang.InterruptedException;

public static void sleep(long millis, int nanos) throws java.lang.InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException("nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}

/**
* Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
* The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
Expand Down
143 changes: 143 additions & 0 deletions vm/JavaAPI/src/java/util/concurrent/TimeUnit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package java.util.concurrent;

public enum TimeUnit {
NANOSECONDS(0),
MICROSECONDS(1),
MILLISECONDS(2),
SECONDS(3),
MINUTES(4),
HOURS(5),
DAYS(6);

private final int index;
TimeUnit(int i) { index = i; }

static final long C0 = 1L;
static final long C1 = C0 * 1000L;
static final long C2 = C1 * 1000L;
static final long C3 = C2 * 1000L;
static final long C4 = C3 * 60L;
static final long C5 = C4 * 60L;
static final long C6 = C5 * 24L;

static final long MAX = Long.MAX_VALUE;

static long x(long d, long m, long over) {
if (d > over) return Long.MAX_VALUE;
if (d < -over) return Long.MIN_VALUE;
return d * m;
}

public long convert(long sourceDuration, TimeUnit sourceUnit) {
switch(this) {
case NANOSECONDS: return sourceUnit.toNanos(sourceDuration);
case MICROSECONDS: return sourceUnit.toMicros(sourceDuration);
case MILLISECONDS: return sourceUnit.toMillis(sourceDuration);
case SECONDS: return sourceUnit.toSeconds(sourceDuration);
case MINUTES: return sourceUnit.toMinutes(sourceDuration);
case HOURS: return sourceUnit.toHours(sourceDuration);
case DAYS: return sourceUnit.toDays(sourceDuration);
default: throw new RuntimeException("Unknown unit");
}
}

public long toNanos(long d) {
if (this == NANOSECONDS) return d;
if (this == MICROSECONDS) return x(d, C1/C0, MAX/(C1/C0));
if (this == MILLISECONDS) return x(d, C2/C0, MAX/(C2/C0));
if (this == SECONDS) return x(d, C3/C0, MAX/(C3/C0));
if (this == MINUTES) return x(d, C4/C0, MAX/(C4/C0));
if (this == HOURS) return x(d, C5/C0, MAX/(C5/C0));
return x(d, C6/C0, MAX/(C6/C0));
}

public long toMicros(long d) {
if (this == NANOSECONDS) return d / (C1/C0);
if (this == MICROSECONDS) return d;
if (this == MILLISECONDS) return x(d, C2/C1, MAX/(C2/C1));
if (this == SECONDS) return x(d, C3/C1, MAX/(C3/C1));
if (this == MINUTES) return x(d, C4/C1, MAX/(C4/C1));
if (this == HOURS) return x(d, C5/C1, MAX/(C5/C1));
return x(d, C6/C1, MAX/(C6/C1));
}

public long toMillis(long d) {
if (this == NANOSECONDS) return d / (C2/C0);
if (this == MICROSECONDS) return d / (C2/C1);
if (this == MILLISECONDS) return d;
if (this == SECONDS) return x(d, C3/C2, MAX/(C3/C2));
if (this == MINUTES) return x(d, C4/C2, MAX/(C4/C2));
if (this == HOURS) return x(d, C5/C2, MAX/(C5/C2));
return x(d, C6/C2, MAX/(C6/C2));
}

public long toSeconds(long d) {
if (this == NANOSECONDS) return d / (C3/C0);
if (this == MICROSECONDS) return d / (C3/C1);
if (this == MILLISECONDS) return d / (C3/C2);
if (this == SECONDS) return d;
if (this == MINUTES) return x(d, C4/C3, MAX/(C4/C3));
if (this == HOURS) return x(d, C5/C3, MAX/(C5/C3));
return x(d, C6/C3, MAX/(C6/C3));
}

public long toMinutes(long d) {
if (this == NANOSECONDS) return d / (C4/C0);
if (this == MICROSECONDS) return d / (C4/C1);
if (this == MILLISECONDS) return d / (C4/C2);
if (this == SECONDS) return d / (C4/C3);
if (this == MINUTES) return d;
if (this == HOURS) return x(d, C5/C4, MAX/(C5/C4));
return x(d, C6/C4, MAX/(C6/C4));
}

public long toHours(long d) {
if (this == NANOSECONDS) return d / (C5/C0);
if (this == MICROSECONDS) return d / (C5/C1);
if (this == MILLISECONDS) return d / (C5/C2);
if (this == SECONDS) return d / (C5/C3);
if (this == MINUTES) return d / (C5/C4);
if (this == HOURS) return d;
return x(d, C6/C5, MAX/(C6/C5));
}

public long toDays(long d) {
if (this == NANOSECONDS) return d / (C6/C0);
if (this == MICROSECONDS) return d / (C6/C1);
if (this == MILLISECONDS) return d / (C6/C2);
if (this == SECONDS) return d / (C6/C3);
if (this == MINUTES) return d / (C6/C4);
if (this == HOURS) return d / (C6/C5);
return d;
}

private int excessNanos(long d, long m) {
if (this == NANOSECONDS) return (int)(d - (m*C2));
if (this == MICROSECONDS) return (int)((d*C1) - (m*C2));
return 0;
}

public void timedWait(Object obj, long timeout) throws InterruptedException {
if (timeout > 0) {
long ms = toMillis(timeout);
int ns = excessNanos(timeout, ms);
obj.wait(ms, ns);
}
}

public void timedJoin(Thread thread, long timeout) throws InterruptedException {
if (timeout > 0) {
long ms = toMillis(timeout);
int ns = excessNanos(timeout, ms);
thread.join(ms, ns);
}
}

public void sleep(long timeout) throws InterruptedException {
if (timeout > 0) {
long ms = toMillis(timeout);
int ns = excessNanos(timeout, ms);
Thread.sleep(ms, ns);
}
}
}
20 changes: 20 additions & 0 deletions vm/JavaAPI/src/java/util/concurrent/locks/Condition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package java.util.concurrent.locks;

import java.util.concurrent.TimeUnit;
import java.util.Date;

public interface Condition {
void await() throws InterruptedException;

void awaitUninterruptibly();

long awaitNanos(long nanosTimeout) throws InterruptedException;

boolean await(long time, TimeUnit unit) throws InterruptedException;

boolean awaitUntil(Date deadline) throws InterruptedException;

void signal();

void signalAll();
}
17 changes: 17 additions & 0 deletions vm/JavaAPI/src/java/util/concurrent/locks/Lock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package java.util.concurrent.locks;

import java.util.concurrent.TimeUnit;

public interface Lock {
void lock();

void lockInterruptibly() throws InterruptedException;

boolean tryLock();

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

void unlock();

Condition newCondition();
}
Loading
Loading