Commit 9acbf5e5 authored by Jesper Öqvist's avatar Jesper Öqvist
Browse files

Export from LJRT repository

parents
# Ignore Gradle files:
/.gradle/
/build/
Realtime library from LJRT compiler.
// Simple build script for Gradle.
apply plugin: 'java'
sourceSets.main.java.srcDir 'src'
compileJava.options.encoding = 'iso-8859-1'
sourceCompatibility = '1.6'
targetCompatibility = '1.6'
/* $Id: Activity.java,v 1.2 2005/08/22 08:18:22 d02en Exp $
*
* Part of LJRTlib - The Lund Java-based Real-Time Library
* Copyright (C) 2005 Dept. of Computer Science, Lund University, Sweden
*
* This is free software under the terms of the GNU LGPL; see License.java
*/
package se.lth.cs.realtime;
/**
* General functionality of concurrent activities; light-weight (threads) or
* heavy-weight (OS) processes.
*
* @see License
*/
public interface Activity {
Timebase getTimebase();
Environment getEnv();
//boolean isStarted();
boolean isAlive();
//boolean isInterrupted();
//void interrupt();
void start();
void join() throws InterruptedException;
void terminate();
}
/* $Id: ActivityImpl.java,v 1.6 2005/08/19 09:37:16 d02en Exp $
*
* Part of LJRTlib - The Lund Java-based Real-Time Library
* Copyright (C) 2005 Dept. of Computer Science, Lund University, Sweden
*
* This is free software under the terms of the GNU LGPL; see License.java
*/
package se.lth.cs.realtime;
/**
* Let a <code>java.lang.Thread</code> object be treated as an <code>Activity</code>,
* which it (almost) is even if that interface (in <code>se.lth.cs.realtime</code>)is
* not implemented (in <code>java.lang</code>). Also threads that already implements
* <code>Activity</code> (instances of <code>JThread</code> and <code>RTThread</code>)
* can be wrapped, thereby ensuring that the constructor always returns a valid activity.
*
* @see License
*/
public final class ActivityImpl implements Activity {
/**
* Encapsulated Java thread.
*/
protected final Thread jActivity;
/**
* Encapsulated real-time thread.
*/
protected final RTThread rtActivity;
/**
* Not part of the <code>Activity</code> interface, obtain the represented
* <code>Thread</source> or <code>RTThread</source>. The intended use of this
* class is only for <code>ActivityEvent</code>s and configuration of activities.
* For example, to support obtaining the actual thread in <code>RTEvent</code>,
* to have the source and owner attributes referring to the actual thread objects,
* the <code>RTEvent</code> base class will use this method. Similar need might
* appear outside this package, hence the protected visibility.
*
* @return the (real-time or Java) tread object.
*/
public Object getThread(){
return (jActivity != null ? (Object)jActivity : (Object)rtActivity);
}
/**
* Create an activity representing the currently executing thread.
*/
public ActivityImpl() {
rtActivity = RTThread.currentRTThread();
if (rtActivity == null) {
jActivity = Thread.currentThread();
} else {
jActivity = null;
}
}
/**
* Make an activity out of a Java thread.
*
* @param thread the Java thread to represent.
*/
public ActivityImpl(Thread thread) {
jActivity = thread;
rtActivity = null;
}
/**
* Create an activity object, that we already have, for completeness.
*
* @param thread the RTThread to be wrapped.
*/
public ActivityImpl(RTThread thread) {
jActivity = null;
rtActivity = thread;
}
/**
* @see se.lth.cs.realtime.Activity#getEnv()
*/
public Environment getEnv() {
return null;
}
/**
* @see se.lth.cs.realtime.Activity#getTimebase()
*/
public Timebase getTimebase() {
return null;
}
/**
* Calls <code>isAlive</code> for the represented thread.
*
* @see se.lth.cs.realtime.Activity#isAlive()
* @see java.lang.Thread#isAlive()
*/
public boolean isAlive() {
return (jActivity != null ? jActivity.isAlive() : rtActivity.isAlive());
}
/**
* Calls <code>isAlive</code> for the represented thread.
*
* @see se.lth.cs.realtime.Activity#isAlive()
* @see java.lang.Thread#isAlive()
*/
public void join() throws InterruptedException {
if (jActivity != null)
jActivity.join();
else
rtActivity.join();
}
/**
* Calls <code>isAlive</code> for the represented thread.
*
* @see se.lth.cs.realtime.JThread#isAlive()
* @see java.lang.Thread#isAlive()
*/
public void start() {
if (jActivity != null)
jActivity.start();
else
rtActivity.start();
}
/**
* Interrupt and join the represented thread.
*
* @see se.lth.cs.realtime.Activity#terminate()
* @see se.lth.cs.realtime.JThread#terminate()
*/
public void terminate() {
if (jActivity != null) {
if (jActivity.isAlive() && !jActivity.isInterrupted()) {
jActivity.interrupt();
try {
jActivity.join();
}
catch (InterruptedException exc) {
throw new RTInterrupted(
"Termination (join) of " + jActivity.getName() + " interrupted");
}
};
}
else {
if (rtActivity.isAlive() && !rtActivity.isInterrupted()) {
rtActivity.interrupt();
try {
rtActivity.join();
}
catch (InterruptedException exc) {
throw new RTInterrupted(
"Termination (join) of " + rtActivity.getName() + " interrupted");
}
};
}
}
}
/* $Id: Condition.java,v 1.8 2005/08/19 09:37:16 d02en Exp $
*
* LJRTlib - The Lund Java-based Real-Time Library
* Copyright (C) 2005 Dept. of Computer Science, Lund University, Sweden
*
* This is free software under the terms of the GNU LGPL; see License.java
*/
package se.lth.cs.realtime;
import se.lth.cs.realtime.semaphore.MutexSem;
/**
* Providing enhanced
* <code>{wait() | wait(timeout) | notify() | notifyAll()} </code> methods,
* acting on the already locked object provided as the first argument for all
* methods. That is, the calling thread must first own the monitor lock via the
* use of synchronized. The enhancements are:
* <ul>
* <li>The optional timeout argument for <code>wait</code> refers to the time
* maintained by the <code>RTSystem</code> base class. If
* <code>RTSystem.DEPLOYED</code> is true, that time is the real time of the
* system, and <code>Condition.wait(timeout)</code> is equivalent to
* <code>Object.wait(timeout)</code>. If <code>RTSystem.DEPLOYED</code> is
* false, which should be the case when the application is run within a
* debugger, time stops when for instance the application/JVM is stopped at a
* breakpoint. Thus, timeouts due to debugging are avoided.
*
* <li>The <code>wait</code> methods do no longer throw
* <code>InterruptedException</code>. Instead, the error
* <code>RTInterrupted</code> is thrown, which optionally can be caught but
* that is not required. Thereby, the risky leftovers of lazy programming, such
* as <code>try {wait();} catch (Exception exc){};</code>, should be avoided
* since it is even simpler to call <code>Condition.wait(this);</code>
*
* <li>Additional versions of <code>wait</code> and <code>notify</code>
* should support condition objects. However, this remains to be implemented.
* </ul>
* Hence, <code>notify()</code> and <code>notifyAll()</code> are not
* changed; they are included here for completeness and simply calls the
* corresponding method in <code>Object</code>.
* <p>
* Remark: The inheritance from RTSystem is purely for the implementation of
* wait with timeout, optionally based on virtual time suitable for debugging.
*
* @see License
*/
public final class Condition {
/**
* The monitor by means of synchronized methods that this object is
* connected to.
*/
private Synchronized syncObj;
/**
* The mutex semaphore used for locking for the case that synchronized
* is not used.
*/
private MutexSem mutex;
/**
* A reference to the factory in which this Condition was created.
*/
private Factory parentFactory;
private int blocked; // Number of threads blocked on this Condition.
private int notification; // Signal counter
private int available; // Remaining actual signal count.
private Condition(MutexSem mutex, Factory parentFactory) {
this.mutex = mutex;
this.parentFactory = parentFactory;
}
private Condition(Monitor monitor, Factory parentFactory) {
this.syncObj = monitor;
this.parentFactory = parentFactory;
}
private Condition(Synchronized.Lock syncObj, Factory parentFactory) {
this.syncObj = syncObj;
this.parentFactory = parentFactory;
}
/**
* A factory which creates condition variables.
*/
public final static class Factory {
private MutexSem mutex = null;
private Monitor monitor = null;
private Synchronized.Lock syncObj = null;
private int condCount = 0;
/**
* This constructor should be used when condition variables
* are used in combination with a mutual exclusion semaphore.
*
* @see se.lth.cs.realtime.semaphore.MutexSem
* @param mutex The mutual exclusion semaphore.
*/
public Factory(MutexSem mutex) {
//Factory.this.mutex = mutex;
this.mutex = mutex;
}
/**
* This constructor should be used when condition variables
* will be used within a Monitor.
*
* @see se.lth.cs.realtime.Monitor
* @param monitor The monitor object.
*/
public Factory(Monitor monitor) {
//Factory.this.monitor = monitor;
this.monitor = monitor;
}
/**
* This constructor should be used when condition variables
* will be used within synchronized blocks and the object,
* which is used for synchronization, need to be used elsewhere.
*
* @see se.lth.cs.realtime.Synchronized
* @param syncObj The synchronization object.
*/
public Factory(Synchronized.Lock syncObj) {
//Factory.this.syncObj = syncObj;
this.syncObj = syncObj;
}
/**
* This constructor should be used when condition variables
* will be used within synchronized block and the object,
* which is used for synchronization, only will be used
* in the calling object. A new lock object will be constructed
* which can be obtained by calling obtainLock().
*/
public Factory() {
syncObj = new Synchronized.Lock();
}
/**
* This method returns the lock object of this factory.
* Calls to this method will only be successful if
* the factory was created with the purpose of creating
* condition variables to be used within synchronized blocks.
*
* @throws UnsupportedOperationException
* When a call is made to a factory constructed to support mutex or monitor synchronization.
*
* @return The lock object of this factory.
*/
public final Synchronized.Lock obtainLock() {
if (syncObj == null) {
throw new UnsupportedOperationException("Lock can not be "
+ "obtained when a Monitor or MutexSem is used for "
+ "synchronization.");
}
return syncObj;
}
/**
* Returns the number of condition variables created by this factory.
* @return The number of condition variables.
*/
public final int getCondCount() {
return condCount;
}
/**
* Creates a new condition variable.
* @return A new condition variable object.
*/
public final Condition newCondition() {
condCount++;
if (mutex != null) {
//return new Condition(mutex, Factory.this);
return new Condition(mutex, this);
} else if (monitor != null) {
//return new Condition(monitor, Factory.this);
return new Condition(monitor, this);
}
//return new Condition(syncObj, Factory.this);
return new Condition(syncObj, this);
}
}
/**
* Waits until this condition variable is signaled.
* The calling thread will be blocked while waiting.
*/
public void await() {
// Oj vilket fulhack!!! Måste få till nåt som verkar funka
// till rtp-projektet bara.
RTThread.sleep(10);
// if (mutex != null) { // Mutex case
// synchronized (syncObj) {
// mutex.give();
// await(syncObj);
// mutex.take();
// }
// } else { // Synchronized, already locked
// if (parentFactory.getCondCount() == 1) {
// await(syncObj);
// } else {
// blocked++;
// int counter = notification;
// while (notification==counter || available==0) {
// await(syncObj);
// }
// available--;
// blocked--;
// }
// }
}
/**
* Waits until this condition variable is signaled or
* the given time limit has expired. The calling thread
* will be blocked while waiting.
*
* @param timeout Maximum wait time in milli seconds.
*/
public void await(long timeout) {
long now;
long arrival = now = System.currentTimeMillis();
if (mutex != null) { // Mutex case
synchronized (syncObj) {
mutex.give();
await(syncObj, timeout);
mutex.take();
}
} else { // Synchronized, already locked
if (parentFactory.getCondCount() == 1) {
await(syncObj, timeout);
} else {
blocked++;
int counter = notification;
while ((notification==counter || available==0) &&
now < (arrival + timeout)) {
await(syncObj, timeout);
now = System.currentTimeMillis();
}
available--;
blocked--;
}
}
}
/**
* Wakes up a thread waiting for this condition
* variable to be signaled. If no threads are waiting
* nothing happens.
*/
public void signal() {
if (mutex != null) { // Mutex case
synchronized (syncObj) {
signal(syncObj);
}
} else { // Synchronized, already locked
if (parentFactory.getCondCount() == 1) {
signal(syncObj);
} else {
if (blocked==0) return;
notification++;
available++;
signalAll(syncObj);
}
}
}
/**
* Wakes up all threads waiting for this condition
* variable to be signaled. If no threads are waiting
* nothing happens.
*/
public void signalAll() {
if (mutex != null) { // Mutex case
synchronized (syncObj) {
signalAll(syncObj);
}
} else { // Synchronized, already locked
if (parentFactory.getCondCount() == 1) {
syncObj.notifyAll();
} else {
if (blocked==0) return;
notification++;
available += blocked;
signalAll(syncObj);
}
}
}
/**
* Replacement for <code>java.lang.Object.notify()</code>, by providing
* <code>this</code> as an argument and thereby not needing to create any
* <code>Condition</code> object.
*
* @param monitor
* the monitor that the caller has locked via synchronized.
* @throws IllegalMonitorStateException
* when the monitor is not held by the calling thread.
*/
public static void signal(Object monitor) {
monitor.notify();
}
/**
* Replacement for <code>java.lang.Object.wait()</code>, to be used with
* <code>this</code> as an argument, assuming that is the locked monitor.
*
* @param monitor
* the monitor that the caller has synchronized upon.
* @throws RTInterrupted
* when the calling thread has been interrupted.
* @throws IllegalMonitorStateException
* when the monitor is not held by the calling thread.
*/
public static void signalAll(Object monitor) {
monitor.notifyAll();
}
/**
* Replacement for <code>java.lang.Object.wait()</code>, to be used with
* <code>this</code> as an argument, assuming that is the locked monitor.
*
* @param monitor
* the monitor that the caller have synchronized upon.
* @throws RTInterrupted
* when the calling thread has been interrupted.
* @throws IllegalMonitorStateException
* when the monitor is not held by the calling thread.
*/
public static void await(Object monitor) {
try {
monitor.wait();
} catch (InterruptedException exc) {
throw new RTInterrupted();
}
}
/**
* Call <code>wait(timeout)</code> in <code>monitor</code>, but
* considering application time before return.
*
* @param monitor
* The object in which notify is waited for.
* @param timeout
* The waiting time after which we want to give up.
*
* @throws IllegalMonitorStateException
* when the monitor is not held by the calling thread.
*/
public static void await(Object monitor, long timeout) {
try {
if (RTSystem.DEPLOYED) {
monitor.wait(timeout);
} else {
// Get a local snapshot of current delay state:
int lag0 = RTSystem.lag;
long now = System.currentTimeMillis();
long t0 = now - RTSystem.lag; // Initial emulated real time.
long dt = timeout; // Remaining time before timeout.
int s = RTSystem.seq; // Lag updated w.r.t. this seq number.
// Stay compatible with wait(0);
if (timeout == 0) {
monitor.wait(0);
return;
}
// Keep on waiting until time is up according to updated virtual
// time:
while (dt >= 0) {
if (dt == 0)
dt = 1; // Avoid wait(0) special case.
monitor.wait(dt);
// Make sure hidden thread has updated lag after wait ready:
s = RTSystem.seq;
Thread.sleep(RTSystem.getTickMillis());
while (RTSystem.seq == s)
Thread.yield();
// If there was a suspend during await, get new time lag:
if (lag0 < RTSystem.lag)
lag0 = RTSystem.lag;
// Update timeout, and loop if virtual time is not up:
now = System.currentTimeMillis();
dt = (t0 + timeout) - (now - RTSystem.lag); // timeout_time -
// current_time