Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/swt/widgets/Synchronizer.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2004 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.swt.widgets;
12  
13  
14  import org.eclipse.swt.*;
15  import org.eclipse.swt.internal.Compatibility;
16   
17  /**
18   * Instances of this class provide synchronization support
19   * for displays. A default instance is created automatically
20   * for each display, and this instance is sufficient for almost
21   * all applications.
22   * <p>
23   * <b>IMPORTANT:</b> Typical application code <em>never</em>
24   * needs to deal with this class. It is provided only to
25   * allow applications which require non-standard
26   * synchronization behavior to plug in the support they
27   * require. <em>Subclasses which override the methods in 
28   * this class must ensure that the superclass methods are
29   * invoked in their implementations</em>
30   * </p>
31   *
32   * @see Display#setSynchronizer
33   */
34  public class Synchronizer {
35    Display display;
36    int messageCount;
37    RunnableLock [] messages;
38    Object messageLock = new Object ();
39    Thread syncThread;
40  
41  public Synchronizer (Display display) {
42    this.display = display;
43  }
44    
45  void addLast (RunnableLock lock) {
46    synchronized (messageLock) {
47      if (messages == null) messages = new RunnableLock [4];
48      if (messageCount == messages.length) {
49        RunnableLock[] newMessages = new RunnableLock [messageCount + 4];
50        System.arraycopy (messages, 0, newMessages, 0, messageCount);
51        messages = newMessages;
52      }
53      messages [messageCount++] = lock;
54      if (messageCount == 1) display.wakeThread ();
55    }
56  }
57  
58  /**
59   * Causes the <code>run()</code> method of the runnable to
60   * be invoked by the user-interface thread at the next 
61   * reasonable opportunity. The caller of this method continues 
62   * to run in parallel, and is not notified when the
63   * runnable has completed.
64   *
65   * @param runnable code to run on the user-interface thread.
66   *
67   * @see #syncExec
68   */
69  protected void asyncExec (Runnable runnable) {
70    if (runnable == null) {
71      display.wake ();
72      return;
73    }
74    addLast (new RunnableLock (runnable));
75  }
76  
77  int getMessageCount () {
78    return messageCount;
79  }
80  
81  void releaseSynchronizer () {
82    display = null;
83    messages = null;
84    messageLock = null;
85    syncThread = null;
86  }
87  
88  RunnableLock removeFirst () {
89    synchronized (messageLock) {
90      if (messageCount == 0) return null;
91      RunnableLock lock = messages [0];
92      System.arraycopy (messages, 1, messages, 0, --messageCount);
93      messages [messageCount] = null;
94      if (messageCount == 0) messages = null;
95      return lock;
96    }
97  }
98  
99  boolean runAsyncMessages () {
100   if (messageCount == 0) return false;
101   RunnableLock lock = removeFirst ();
102   if (lock == null) return true;
103   synchronized (lock) {
104     syncThread = lock.thread;
105     try {
106       lock.run ();
107     } catch (Throwable t) {
108       lock.throwable = t;
109       SWT.error (SWT.ERROR_FAILED_EXEC, t);
110     } finally {
111       syncThread = null;
112       lock.notifyAll ();
113     }
114   }
115   return true;
116 }
117 
118 
119 /**
120  * Causes the <code>run()</code> method of the runnable to
121  * be invoked by the user-interface thread at the next 
122  * reasonable opportunity. The thread which calls this method
123  * is suspended until the runnable completes.
124  *
125  * @param runnable code to run on the user-interface thread.
126  *
127  * @exception SWTException <ul>
128  *    <li>ERROR_FAILED_EXEC - if an exception occured when executing the runnable</li>
129  * </ul>
130  *
131  * @see #asyncExec
132  */
133 protected void syncExec (Runnable runnable) {
134   if (display.isValidThread ()) {
135     if (runnable != null) runnable.run ();
136     return;
137   }
138   if (runnable == null) {
139     display.wake ();
140     return;
141   }
142   RunnableLock lock = new RunnableLock (runnable);
143   /*
144    * Only remember the syncThread for syncExec.
145    */
146   lock.thread = Thread.currentThread();
147   synchronized (lock) {
148     addLast (lock);
149     boolean interrupted = false;
150     while (!lock.done ()) {
151       try {
152         lock.wait ();
153       } catch (InterruptedException e) {
154         interrupted = true;
155       }
156     }
157     if (interrupted) {
158       Compatibility.interrupt();
159     }
160     if (lock.throwable != null) {
161       SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable);
162     }
163   }
164 }
165 
166 }