2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 * @author Mikhail Danilov
21 package org.apache.harmony.awt.wtk;
23 import java.util.Hashtable;
24 import java.util.LinkedList;
26 import org.apache.harmony.awt.internal.nls.Messages;
29 * Class synchronizer is to protect AWT state integrity in multithreading environment.
30 * It is supposed to have a child class per native platform.
31 * The only instance is created on the first use of one of the core AWT classes.
32 * Registers WTK on the dispatch thread startup.
33 * It is just a special kind of mutex.
37 public class Synchronizer {
38 //TODO: think about java.util.concurrent use for faster blocking/awaking operations
39 //TODO: think about all synchronized methods. Is there need to synchronize everything?
42 * This field holds the counter of lock operation.
43 * To free synchronizer unlock method must be called $acquestCounter times.
44 * Equals to 0 when synchronizer is free.
46 protected int acquestCounter;
49 * This field holds the owner of synchronizer.
50 * Owner of synchronizer is a last thread that successfully locked synchronizer and
51 * still havn't freed it. Equals to null when synchronizer is free.
53 protected Thread owner;
56 * This field holds the wait queue.
57 * Wait queue is a queue where thread wait for synchronizer access.
58 * Empty when synchronizer is free.
60 protected final LinkedList<Thread> waitQueue = new LinkedList<Thread>();
63 * The event dispatch thread
65 protected Thread dispatchThread;
67 private final Hashtable<Thread, Integer> storedStates = new Hashtable<Thread, Integer>();
70 * Acquire the lock for this synchronizer. Nested lock is supported.
71 * If the mutex is already locked by another thread, the current thread will be put
72 * into wait queue until the lock becomes available.
73 * All user threads are served in FIFO order. Dispatch thread has higher priority.
74 * Supposed to be used in Toolkit.lockAWT() only.
78 Thread curThread = Thread.currentThread();
80 if (acquestCounter == 0) {
84 if (owner == curThread) {
87 if (curThread == dispatchThread) {
88 waitQueue.addFirst(curThread);
90 waitQueue.addLast(curThread);
94 } catch (InterruptedException e) {
95 if (owner != curThread) {
96 waitQueue.remove(curThread);
97 // awt.1F=Waiting for resource access thread interrupted not from unlock method.
98 throw new RuntimeException(Messages
99 .getString("awt.1F")); //$NON-NLS-1$
108 * Release the lock for this synchronizer.
109 * If wait queue is not empty the first waiting thread acquires the lock.
110 * Supposed to be used in Toolkit.unlockAWT() only.
112 public void unlock() {
113 synchronized (this) {
114 if (acquestCounter == 0) {
115 // awt.20=Can't unlock not locked resource.
116 throw new RuntimeException(Messages.getString("awt.20")); //$NON-NLS-1$
118 if (owner != Thread.currentThread()) {
119 // awt.21=Not owner can't unlock resource.
120 throw new RuntimeException(Messages.getString("awt.21")); //$NON-NLS-1$
124 if (acquestCounter == 0) {
125 if (waitQueue.size() > 0) {
127 owner = waitQueue.removeFirst();
137 * Stores state of this synchronizer and frees it.
138 * Supposed to be used in Toolkit.unsafeInvokeAndWaitUnderAWTLock() only in pair with
139 * lockAndRestoreState().
140 * Do not call it directly.
142 public void storeStateAndFree() {
143 synchronized (this) {
144 Thread curThread = Thread.currentThread();
146 if (owner != curThread) {
147 // awt.22=Not owner can't free resource.
148 throw new RuntimeException(Messages.getString("awt.22")); //$NON-NLS-1$
150 if (storedStates.containsKey(curThread)) {
151 // awt.23=One thread can't store state several times in a row.
152 throw new RuntimeException(Messages.getString("awt.23")); //$NON-NLS-1$
155 storedStates.put(curThread, new Integer(acquestCounter));
162 * Locks this synchronizer and restores it's state.
163 * Supposed to be used in Toolkit.unsafeInvokeAndWaitUnderAWTLock() only in pair with
164 * storeStateAndFree().
165 * Do not call it directly.
167 public void lockAndRestoreState() {
168 synchronized (this) {
169 Thread curThread = Thread.currentThread();
171 if (owner == curThread) {
172 // awt.24=Owner can't overwrite resource state. Lock operations may be lost.
173 throw new RuntimeException(
174 Messages.getString("awt.24")); //$NON-NLS-1$
176 if (!storedStates.containsKey(curThread)) {
177 // awt.25=No state stored for current thread.
178 throw new RuntimeException(Messages.getString("awt.25")); //$NON-NLS-1$
182 acquestCounter = storedStates.get(curThread).intValue();
183 storedStates.remove(curThread);
188 * Sets references to WTK and event dispatch thread.
189 * Called on toolkit startup.
191 * @param wtk - reference to WTK instance
192 * @param dispatchThread - reference to event dispatch thread
194 public void setEnvironment(WTK wtk, Thread dispatchThread) {
195 synchronized (this) {
196 this.dispatchThread = dispatchThread;