/* THIS CODE IS CURRENTLY NOT IN USE ANYWHERE IN ABBOTFORSWT
* An attempt to subclass org.eclipse.swt.widgets.Synchronizer in order
* to provide a public API for coordination with calls to Display.syncExec(Runnable).
*
* NOTE: Most of the code here is copied from org.eclipse.swt.widgets.Synchronizer.
*/
package abbot.swt;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.internal.Compatibility;
import org.eclipse.swt.SWT;
public class AbbotSynchronizer extends org.eclipse.swt.widgets.Synchronizer{
public static final String copyright = "Licensed Materials -- Property of IBM\n"+
"(c) Copyright International Business Machines Corporation, 2003\nUS Government "+
"Users Restricted Rights - Use, duplication or disclosure restricted by GSA "+
"ADP Schedule Contract with IBM Corp.";
/**
* Instances of this class are used to ensure that an
* application cannot interfere with the locking mechanism
* used to implement asynchonous and synchronous communication
* between widgets and background threads.
*/
class RunnableLock {
Runnable runnable;
Thread thread;
Throwable throwable;
RunnableLock (Runnable runnable) {
this.runnable = runnable;
}
boolean done () {
return runnable == null || throwable != null;
}
void run () {
if (runnable != null) runnable.run ();
runnable = null;
}
}
Display display;
int messageCount;
RunnableLock [] messages;
Object messageLock = new Object ();
Thread syncThread;
public AbbotSynchronizer(Display display){
super(display);
this.display = display;
}
void addLast (RunnableLock lock) {
synchronized (messageLock) {
if (messages == null) messages = new RunnableLock [4];
if (messageCount == messages.length) {
RunnableLock[] newMessages = new RunnableLock [messageCount + 4];
System.arraycopy (messages, 0, newMessages, 0, messageCount);
messages = newMessages;
}
messages [messageCount++] = lock;
}
}
/**
* Causes the <code>run()</code> method of the runnable to
* be invoked by the user-interface thread at the next
* reasonable opportunity. The caller of this method continues
* to run in parallel, and is not notified when the
* runnable has completed.
*
* @param runnable code to run on the user-interface thread.
*
* @see #syncExec
*/
protected void asyncExec (Runnable runnable) {
if (runnable != null) addLast (new RunnableLock (runnable));
display.wake ();
}
int getMessageCount () {
return messageCount;
}
void releaseSynchronizer () {
display = null;
messages = null;
messageLock = null;
syncThread = null;
}
RunnableLock removeFirst () {
synchronized (messageLock) {
if (messageCount == 0) return null;
RunnableLock lock = messages [0];
System.arraycopy (messages, 1, messages, 0, --messageCount);
messages [messageCount] = null;
if (messageCount == 0) messages = null;
return lock;
}
}
boolean runAsyncMessages () {
if (messageCount == 0) return false;
RunnableLock lock = removeFirst ();
if (lock == null) return true;
synchronized (lock) {
syncThread = lock.thread;
try {
lock.run ();
} catch (Throwable t) {
lock.throwable = t;
SWT.error (SWT.ERROR_FAILED_EXEC, t);
} finally {
syncThread = null;
lock.notifyAll ();
}
}
return true;
}
/**
* Causes the <code>run()</code> method of the runnable to
* be invoked by the user-interface thread at the next
* reasonable opportunity. The thread which calls this method
* is suspended until the runnable completes.
*
* @param runnable code to run on the user-interface thread.
*
* @exception SWTException <ul>
* <li>ERROR_FAILED_EXEC - if an exception occured when executing the runnable</li>
* </ul>
*
* @see #asyncExec
*/
protected void syncExec (Runnable runnable) {
if (Thread.currentThread()== display.getThread()) {
if (runnable != null) runnable.run ();
return;
}
if (runnable == null) {
display.wake ();
return;
}
RunnableLock lock = new RunnableLock (runnable);
/*
* Only remember the syncThread for syncExec.
*/
lock.thread = Thread.currentThread();
/* NEW CODE */
Display callingThreadsDisplay = Display.findDisplay(lock.thread);
final int WAIT_TIME_NS = 10;
/* END NEW CODE */
synchronized (lock) {
addLast (lock);
display.wake ();
boolean interrupted = false;
while (!lock.done ()) {
try {
/* CHANGED CODE */
lock.wait (0, WAIT_TIME_NS); // was 'lock.wait();'
/* END CHANGED CODE */
/* NEW CODE */
if(callingThreadsDisplay!=null && !callingThreadsDisplay.isDisposed()){
callingThreadsDisplay.readAndDispatch();
}
/* END NEW CODE */
} catch (InterruptedException e) {
interrupted = true;
}
}
if (interrupted) {
Compatibility.interrupt();
}
if (lock.throwable != null) {
SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable);
}
}
}
}