001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal;
011:
012: import java.util.ArrayList;
013: import java.util.Iterator;
014: import java.util.List;
015:
016: import org.eclipse.swt.widgets.Display;
017: import org.eclipse.swt.widgets.Synchronizer;
018: import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
019:
020: public class UISynchronizer extends Synchronizer {
021: protected UILockListener lockListener;
022:
023: /**
024: * Indicates that the UI is in startup mode and that no non-workbench
025: * runnables should be invoked.
026: */
027: protected boolean isStarting = true;
028:
029: /**
030: * List of non-workbench Runnables that need executing at some point in the future
031: */
032: protected List pendingStartup = new ArrayList();
033:
034: /**
035: * Setting this variable to the value {@link Boolean#TRUE} will allow a
036: * thread to execute code during the startup sequence.
037: */
038: public static final ThreadLocal startupThread = new ThreadLocal() {
039:
040: /*
041: * (non-Javadoc)
042: *
043: * @see java.lang.ThreadLocal#initialValue()
044: */
045: protected Object initialValue() {
046: return Boolean.FALSE;
047: }
048:
049: /* (non-Javadoc)
050: * @see java.lang.ThreadLocal#set(java.lang.Object)
051: */
052: public void set(Object value) {
053: if (value != Boolean.TRUE && value != Boolean.FALSE)
054: throw new IllegalArgumentException();
055: super .set(value);
056: }
057: };
058:
059: public UISynchronizer(Display display, UILockListener lock) {
060: super (display);
061: this .lockListener = lock;
062: }
063:
064: public void started() {
065: synchronized (this ) {
066: if (!isStarting)
067: throw new IllegalStateException();
068: isStarting = false;
069: for (Iterator i = pendingStartup.iterator(); i.hasNext();) {
070: Runnable runnable = (Runnable) i.next();
071: try {
072: //queue up all pending asyncs
073: super .asyncExec(runnable);
074: } catch (RuntimeException e) {
075: // do nothing
076: }
077: }
078: pendingStartup = null;
079: // wake up all pending syncExecs
080: this .notifyAll();
081: }
082: }
083:
084: /* (non-Javadoc)
085: * @see org.eclipse.swt.widgets.Synchronizer#asyncExec(java.lang.Runnable)
086: */
087: protected void asyncExec(Runnable runnable) {
088: if (runnable != null) {
089: synchronized (this ) {
090: if (isStarting
091: && !(runnable instanceof StartupRunnable)) {
092: pendingStartup.add(runnable);
093:
094: return;
095: }
096: }
097: }
098: super .asyncExec(runnable);
099: }
100:
101: public void syncExec(Runnable runnable) {
102:
103: synchronized (this ) {
104: if (isStarting
105: && UISynchronizer.startupThread.get() == Boolean.FALSE) {
106: do {
107: try {
108: this .wait();
109: } catch (InterruptedException e) {
110: }
111: } while (isStarting);
112: }
113: }
114:
115: //if this thread is the UI or this thread does not own any locks, just do the syncExec
116: if ((runnable == null) || lockListener.isUI()
117: || !lockListener.isLockOwner()) {
118: super .syncExec(runnable);
119: return;
120: }
121: Semaphore work = new Semaphore(runnable);
122: work.setOperationThread(Thread.currentThread());
123: lockListener.addPendingWork(work);
124: asyncExec(new Runnable() {
125: public void run() {
126: lockListener.doPendingWork();
127: }
128: });
129: try {
130: //even if the UI was not blocked earlier, it might become blocked
131: //before it can serve the asyncExec to do the pending work
132: do {
133: if (lockListener.isUIWaiting()) {
134: lockListener.interruptUI();
135: }
136: } while (!work.acquire(1000));
137: } catch (InterruptedException e) {
138: }
139: }
140: }
|