]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Synchronizer.java
Remove invalid SHA-256-Digests
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Synchronizer.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2014 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.widgets;
15
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.graphics.*;
18
19 /**
20  * Instances of this class provide synchronization support
21  * for displays. A default instance is created automatically
22  * for each display, and this instance is sufficient for almost
23  * all applications.
24  * <p>
25  * <b>IMPORTANT:</b> Typical application code <em>never</em>
26  * needs to deal with this class. It is provided only to
27  * allow applications which require non-standard
28  * synchronization behavior to plug in the support they
29  * require. <em>Subclasses which override the methods in
30  * this class must ensure that the superclass methods are
31  * invoked in their implementations</em>
32  * </p>
33  *
34  * @see Display#setSynchronizer
35  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
36  */
37 public class Synchronizer {
38         Display display;
39         int messageCount;
40         RunnableLock [] messages;
41         Object messageLock = new Object ();
42         Thread syncThread;
43         static final int GROW_SIZE = 4;
44         static final int MESSAGE_LIMIT = 64;
45
46         //TEMPORARY CODE
47         static final boolean IS_COCOA = "cocoa".equals (SWT.getPlatform ());
48         static final boolean IS_GTK = "gtk".equals (SWT.getPlatform ());
49
50 /**
51  * Constructs a new instance of this class.
52  *
53  * @param display the display to create the synchronizer on
54  */
55 public Synchronizer (Display display) {
56         this.display = display;
57 }
58
59 /**
60  * Removes all pending events from the receiver and inserts them into the beginning of the given
61  * synchronizer's queue
62  *
63  * @param toReceiveTheEvents the synchronizer that will receive the events
64  */
65 void moveAllEventsTo (Synchronizer toReceiveTheEvents) {
66         RunnableLock[] oldMessages;
67         int oldMessageCount;
68         synchronized (messageLock) {
69                 oldMessages = messages;
70                 messages = null;
71                 oldMessageCount = messageCount;
72                 messageCount = 0;
73         }
74         toReceiveTheEvents.addFirst(oldMessages, oldMessageCount);
75 }
76
77 /**
78  * Adds the given events to the beginning of the message queue, to
79  * be processed in order.
80  *
81  * @param toAdd events to add. Permits null if and only if numToAdd is 0.
82  * @param numToAdd number of events to add from the beginning of the given array.
83  */
84 void addFirst (RunnableLock[] toAdd, int numToAdd) {
85         if (numToAdd <= 0) {
86                 return;
87         }
88         boolean wake = false;
89         synchronized (messageLock) {
90                 int nextSize = messageCount + Math.max(numToAdd, GROW_SIZE);
91                 if (messages == null)
92                         messages = new RunnableLock[nextSize];
93                 if (messages.length < messageCount + numToAdd) {
94                         RunnableLock[] newMessages = new RunnableLock[nextSize];
95                         System.arraycopy(messages, 0, newMessages, numToAdd, messageCount);
96                         messages = newMessages;
97                 } else {
98                         System.arraycopy(messages, 0, messages, numToAdd, messageCount);
99                 }
100                 System.arraycopy(toAdd, 0, messages, 0, numToAdd);
101                 wake = (messageCount == 0);
102                 messageCount += numToAdd;
103         }
104         if (wake)
105                 display.wakeThread();
106 }
107
108 void addLast (RunnableLock lock) {
109         boolean wake = false;
110         synchronized (messageLock) {
111                 if (messages == null) messages = new RunnableLock [GROW_SIZE];
112                 if (messageCount == messages.length) {
113                         RunnableLock[] newMessages = new RunnableLock [messageCount + GROW_SIZE];
114                         System.arraycopy (messages, 0, newMessages, 0, messageCount);
115                         messages = newMessages;
116                 }
117                 messages [messageCount++] = lock;
118                 wake = messageCount == 1;
119         }
120         if (wake) display.wakeThread ();
121 }
122
123 /**
124  * Causes the <code>run()</code> method of the runnable to
125  * be invoked by the user-interface thread at the next
126  * reasonable opportunity. The caller of this method continues
127  * to run in parallel, and is not notified when the
128  * runnable has completed.
129  *
130  * @param runnable code to run on the user-interface thread.
131  *
132  * @see #syncExec
133  */
134 protected void asyncExec (Runnable runnable) {
135         if (runnable == null) {
136                 //TEMPORARY CODE
137                 if (!(IS_GTK || IS_COCOA)) {
138                         display.wake ();
139                         return;
140                 }
141         }
142         addLast (new RunnableLock (runnable));
143 }
144
145 int getMessageCount () {
146         synchronized (messageLock) {
147                 return messageCount;
148         }
149 }
150
151 void releaseSynchronizer () {
152         display = null;
153         messages = null;
154         messageLock = null;
155         syncThread = null;
156 }
157
158 RunnableLock removeFirst () {
159         synchronized (messageLock) {
160                 if (messageCount == 0) return null;
161                 RunnableLock lock = messages [0];
162                 System.arraycopy (messages, 1, messages, 0, --messageCount);
163                 messages [messageCount] = null;
164                 if (messageCount == 0) {
165                         if (messages.length > MESSAGE_LIMIT) messages = null;
166                 }
167                 return lock;
168         }
169 }
170
171 boolean runAsyncMessages () {
172         return runAsyncMessages (false);
173 }
174
175 boolean runAsyncMessages (boolean all) {
176         boolean run = false;
177         do {
178                 RunnableLock lock = removeFirst ();
179                 if (lock == null) return run;
180                 run = true;
181                 synchronized (lock) {
182                         syncThread = lock.thread;
183                         display.sendPreEvent(SWT.None);
184                         try {
185                                 lock.run (display);
186                         } catch (Throwable t) {
187                                 lock.throwable = t;
188                                 SWT.error (SWT.ERROR_FAILED_EXEC, t);
189                         } finally {
190                                 if (display != null && !display.isDisposed()) {
191                                         display.sendPostEvent(SWT.None);
192                                 }
193                                 syncThread = null;
194                                 lock.notifyAll ();
195                         }
196                 }
197         } while (all);
198         return run;
199 }
200
201 /**
202  * Causes the <code>run()</code> method of the runnable to
203  * be invoked by the user-interface thread at the next
204  * reasonable opportunity. The thread which calls this method
205  * is suspended until the runnable completes.
206  *
207  * @param runnable code to run on the user-interface thread.
208  *
209  * @exception SWTException <ul>
210  *    <li>ERROR_FAILED_EXEC - if an exception occurred when executing the runnable</li>
211  * </ul>
212  *
213  * @see #asyncExec
214  */
215 protected void syncExec (Runnable runnable) {
216         RunnableLock lock = null;
217         synchronized (Device.class) {
218                 if (display == null || display.isDisposed ()) SWT.error (SWT.ERROR_DEVICE_DISPOSED);
219                 if (!display.isValidThread ()) {
220                         if (runnable == null) {
221                                 display.wake ();
222                                 return;
223                         }
224                         lock = new RunnableLock (runnable);
225                         /*
226                          * Only remember the syncThread for syncExec.
227                          */
228                         lock.thread = Thread.currentThread();
229                         addLast (lock);
230                 }
231         }
232         if (lock == null) {
233                 if (runnable != null) {
234                         display.sendPreEvent(SWT.None);
235                         try {
236                                 runnable.run();
237                         } catch (RuntimeException exception) {
238                                 display.getRuntimeExceptionHandler ().accept (exception);
239                         } catch (Error error) {
240                                 display.getErrorHandler ().accept (error);
241                         } finally {
242                                 if (display != null && !display.isDisposed()) {
243                                         display.sendPostEvent(SWT.None);
244                                 }
245                         }
246                 }
247                 return;
248         }
249         synchronized (lock) {
250                 boolean interrupted = false;
251                 while (!lock.done ()) {
252                         try {
253                                 lock.wait ();
254                         } catch (InterruptedException e) {
255                                 interrupted = true;
256                         }
257                 }
258                 if (interrupted) {
259                         Thread.currentThread().interrupt();
260                 }
261                 if (lock.throwable != null) {
262                         SWT.error (SWT.ERROR_FAILED_EXEC, lock.throwable);
263                 }
264         }
265 }
266
267 }