KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > text > Deadlock40766Test


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20
21 package org.openide.text;
22
23
24
25 import java.io.IOException JavaDoc;
26 import javax.swing.text.*;
27 import junit.textui.TestRunner;
28 import org.netbeans.junit.*;
29 import org.openide.util.Exceptions;
30 import org.openide.util.RequestProcessor;
31
32 /**
33  * Exception during load of the document can cause starvation
34  * in the thread that waits for that to happen.
35  *
36  * @author Petr Nejedly, Jaroslav Tulach
37  */

38 public class Deadlock40766Test extends NbTestCase implements CloneableEditorSupport.Env {
39     /** the support to work with */
40     private CES support;
41     // Env variables
42
private String JavaDoc content = "Hello";
43     private boolean valid = true;
44     private boolean modified = false;
45     /** if not null contains message why this document cannot be modified */
46     private String JavaDoc cannotBeModified;
47     private java.util.Date JavaDoc date = new java.util.Date JavaDoc ();
48     private java.util.List JavaDoc/*<java.beans.PropertyChangeListener>*/ propL = new java.util.ArrayList JavaDoc ();
49     private java.beans.VetoableChangeListener JavaDoc vetoL;
50     
51     /** Creates new TextTest */
52     public Deadlock40766Test(String JavaDoc s) {
53         super(s);
54     }
55     
56     public static void main(String JavaDoc[] args) {
57         TestRunner.run(new NbTestSuite(Deadlock40766Test.class));
58     }
59
60     protected void setUp () {
61         support = new CES (this, org.openide.util.Lookup.EMPTY);
62     }
63     
64     RequestProcessor my = new RequestProcessor("my");
65     
66     public void testDeadlock40766() throws Exception JavaDoc {
67         org.openide.util.Task task;
68         
69         synchronized (support.helperLock) {
70             my.post (support);
71             // wait for the support (another thread) to try to open and block
72
support.helperLock.wait ();
73         }
74         
75         // now the RP if after the doc test but have not locked
76
// let's change the state now.
77

78         StyledDocument doc = support.openDocument();
79         
80         synchronized (support.helperLock) {
81             // wait till it gets into support lock
82
support.helperLock.notifyAll();
83             support.helperLock.wait (1000);
84         }
85
86         // now the RP holds lock but doesn't have doc readAccess
87

88         NbDocument.runAtomic(doc, new Runnable JavaDoc() {
89             public void run() {
90                 synchronized (support.helperLock) {
91                     support.helperLock.notifyAll();
92                 }
93                 
94                 try {
95                     support.openDocument();
96                 } catch (IOException JavaDoc ioe) {
97                     fail(ioe.getMessage());
98                 }
99                 
100             }
101         });
102         
103     }
104     
105     /* #38013 was a deadlock where:
106      * 1) one thread started adding PositionRef before the document was loaded,
107      * slept for a while on a synchronized and awakened with newly load
108      * documet that it needed to readlock.
109      * 2) second thread loaded the document and wanted to convert positions
110      * from inside its writelock.
111      *
112      * Reproduction:
113      * 1. Start thread A, let it try to add PositionRef without a doc.
114      * As soon as it acquires PR$M lock, switch to B
115      * 2. Start thread B, wait for A thread's rendezvous, start loading
116      * document (which spawns thread C)
117      * after 1000ms unblock thread A (C should already have locked document)
118      */

119     public void testDeadlock38013() throws Exception JavaDoc {
120         org.openide.util.Task task;
121
122         // this is thread B
123

124         synchronized (support.helperLock) {
125             my.post (support); // thread A
126
support.helperLock.wait ();
127             // we've got the beforeLock notification, we need the "after" one
128
// so let's respin the locks
129
support.helperLock.notifyAll();
130             support.helperLock.wait ();
131         }
132         //now, B have the RP.M's lock and we have 1000 ms to lock
133
// the document and try to get PR.M's lock from C
134

135         StyledDocument doc = support.openDocument();
136         
137     }
138
139     public void testCreatePositionCanBeCalledFromWriteLockOnDocument () throws Exception JavaDoc {
140         final StyledDocument doc = support.openDocument ();
141         
142         class R implements Runnable JavaDoc {
143             boolean inAtomic;
144             PositionRef ref;
145             
146             public void run () {
147                 if (!inAtomic) {
148                     inAtomic = true;
149                     NbDocument.runAtomic (doc, this);
150                     return;
151                 }
152                 
153                 synchronized (this) {
154                     notifyAll ();
155                     try {
156                         wait (1000);
157                     } catch (InterruptedException JavaDoc ex) {
158                         fail (ex.getMessage ());
159                     }
160                 }
161                 ref = support.createPositionRef (0, Position.Bias.Backward);
162             }
163         }
164         
165         RequestProcessor.Task task;
166         R r = new R ();
167         synchronized (r) {
168             task = RequestProcessor.getDefault ().post (r);
169             r.wait ();
170         }
171         
172         // now R holds write lock on the document, and will wake up soon
173
// grab the lock from oposite site
174
PositionRef ref = support.createPositionRef (1, Position.Bias.Backward);
175         
176         assertNotNull ("Ref created", ref);
177         task.waitFinished ();
178         assertNotNull ("Ref1 crated", r.ref);
179         
180     } // end of testCreatePositionCanBeCalledFromWriteLockOnDocument
181

182     //
183
// Implementation of the CloneableEditorSupport.Env
184
//
185

186     public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener JavaDoc l) {
187         propL.add (l);
188     }
189     public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener JavaDoc l) {
190         propL.remove (l);
191     }
192     
193     public synchronized void addVetoableChangeListener(java.beans.VetoableChangeListener JavaDoc l) {
194         assertNull ("This is the first veto listener", vetoL);
195         vetoL = l;
196     }
197     public void removeVetoableChangeListener(java.beans.VetoableChangeListener JavaDoc l) {
198         assertEquals ("Removing the right veto one", vetoL, l);
199         vetoL = null;
200     }
201     
202     public org.openide.windows.CloneableOpenSupport findCloneableOpenSupport() {
203         return support;
204     }
205     
206     public String JavaDoc getMimeType() {
207         return "text/plain";
208     }
209     
210     public java.util.Date JavaDoc getTime() {
211         return date;
212     }
213     
214     public java.io.InputStream JavaDoc inputStream() throws java.io.IOException JavaDoc {
215         return new java.io.ByteArrayInputStream JavaDoc (content.getBytes ());
216     }
217     public java.io.OutputStream JavaDoc outputStream() throws java.io.IOException JavaDoc {
218         class ContentStream extends java.io.ByteArrayOutputStream JavaDoc {
219             public void close () throws java.io.IOException JavaDoc {
220                 super.close ();
221                 content = new String JavaDoc (toByteArray ());
222             }
223         }
224         
225         return new ContentStream ();
226     }
227     
228     public boolean isValid() {
229         return valid;
230     }
231     
232     public boolean isModified() {
233         return modified;
234     }
235
236     public void markModified() throws java.io.IOException JavaDoc {
237         if (cannotBeModified != null) {
238             IOException JavaDoc e = new IOException JavaDoc ();
239             Exceptions.attachLocalizedMessage(e, cannotBeModified);
240             throw e;
241         }
242         
243         modified = true;
244     }
245     
246     public void unmarkModified() {
247         modified = false;
248     }
249
250     /** Implementation of the CES */
251     private final class CES extends CloneableEditorSupport implements Runnable JavaDoc {
252         
253         public CES (Env env, org.openide.util.Lookup l) {
254             super (env, l);
255         }
256         
257         protected String JavaDoc messageName() {
258             return "Name";
259         }
260         
261         protected String JavaDoc messageOpened() {
262             return "Opened";
263         }
264         
265         protected String JavaDoc messageOpening() {
266             return "Opening";
267         }
268         
269         protected String JavaDoc messageSave() {
270             return "Save";
271         }
272         
273         protected String JavaDoc messageToolTip() {
274             return "ToolTip";
275         }
276         
277         
278         protected StyledDocument createStyledDocument (EditorKit kit) {
279             class Doc extends DefaultStyledDocument implements NbDocument.WriteLockable {
280                 public void runAtomic (Runnable JavaDoc r) {
281                     writeLock();
282                     try {
283                         r.run();
284                     } finally {
285                         writeUnlock();
286                     }
287                 }
288                 public void runAtomicAsUser (Runnable JavaDoc r) {
289                     runAtomic(r);
290                 }
291             }
292             StyledDocument sd = new Doc();
293             return sd;
294         }
295
296         Object JavaDoc helperLock = new Object JavaDoc();
297
298         void howToReproduceDeadlock40766(boolean beforeLock) {
299             if (my.isRequestProcessorThread()) {
300                 synchronized(helperLock) {
301                     try {
302                         helperLock.notifyAll();
303                         helperLock.wait(1000);
304                     } catch (InterruptedException JavaDoc ie) {
305                         fail (ie.getMessage ());
306                     }
307                 }
308             }
309         }
310         
311         public void run () {
312             createPositionRef(0, Position.Bias.Forward);
313         }
314
315     } // end of CES
316
}
317
Popular Tags