KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > util > MutexTest


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 package org.openide.util;
21
22 import java.io.IOException JavaDoc;
23 import java.lang.ref.*;
24 import java.lang.reflect.InvocationTargetException JavaDoc;
25 import java.util.*;
26 import java.util.concurrent.atomic.AtomicBoolean JavaDoc;
27 import java.util.logging.Level JavaDoc;
28 import java.util.logging.Logger JavaDoc;
29 import junit.framework.*;
30 import org.netbeans.junit.*;
31
32 public class MutexTest extends NbTestCase {
33     Mutex.Privileged p;
34     Mutex m;
35
36
37
38     public MutexTest(java.lang.String JavaDoc testName) {
39         super(testName);
40     }
41
42     public static void main(java.lang.String JavaDoc[] args) {
43         junit.textui.TestRunner.run(suite());
44     }
45     
46     public static Test suite() {
47         NbTestSuite suite = new NbTestSuite(MutexTest.class);
48
49         return suite;
50     }
51     
52     /** Sets up the test.
53      */

54     protected void setUp () {
55         p = new Mutex.Privileged ();
56         m = new Mutex (p);
57         Mutex.beStrict = true;
58     }
59     
60     public void testReadWriteRead() throws Exception JavaDoc {
61         
62         final Object JavaDoc lock = new Object JavaDoc();
63         final Mutex.Privileged mPriv = new Mutex.Privileged();
64         final Mutex m = new Mutex( mPriv );
65         
66         synchronized ( lock ) {
67             mPriv.enterReadAccess();
68             
69             new Thread JavaDoc() {
70                 public void run () {
71                     synchronized( lock ) {
72                         lock.notifyAll();
73                     }
74                     mPriv.enterWriteAccess();
75                     synchronized ( lock ) {
76                         lock.notifyAll();
77                         mPriv.exitWriteAccess();
78                     }
79                 }
80             }.start();
81             
82             lock.wait();
83                        
84         }
85         Thread.sleep (100);
86         
87         mPriv.enterReadAccess();
88         
89         mPriv.exitReadAccess();
90         
91         synchronized ( lock ) {
92             mPriv.exitReadAccess();
93             lock.wait();
94         }
95     }
96     
97     /** Simple test to execute read access and write access imediatelly.
98      */

99     public void testPostImmediatelly () {
100         State s = new State ();
101         
102         m.postReadRequest(s);
103         
104         if (s.state != 1) {
105             fail ("Read request not started immediatelly");
106         }
107         
108         m.postWriteRequest (s);
109         
110         if (s.state != 2) {
111             fail ("Write request not started immediately");
112         }
113     }
114
115     /** Behaviour of postWriteRequest is defined by this test.
116      */

117     public void testPostWriteRequest () {
118         
119         State s = new State ();
120         
121         // first enter
122
p.enterWriteAccess ();
123             p.enterReadAccess ();
124         
125             m.postWriteRequest(s);
126             
127             if (s.state != 0) {
128                 fail ("Write request started when we are in read access");
129             }
130                 
131             p.exitReadAccess ();
132             
133         if (s.state != 1) {
134             fail ("Write request not run when leaving read access: " + s.state);
135         }
136                 
137         // exiting
138
p.exitWriteAccess ();
139         
140         if (s.state != 1) {
141             fail ("Run more times?: " + s.state);
142         }
143     }
144     
145     /** Behaviour of postReadRequest is defined by this test.
146      */

147     public void testPostReadRequest () {
148         
149         State s = new State ();
150         
151         // first enter
152
p.enterWriteAccess ();
153         
154             m.postReadRequest(s);
155             
156             if (s.state != 0) {
157                 fail ("Read request started when we are in write access");
158             }
159                 
160             p.exitWriteAccess ();
161             
162             if (s.state != 1) {
163                 fail ("Read request not run when leaving write access: " + s.state);
164             }
165                 
166         
167         if (s.state != 1) {
168             fail ("Run more times?: " + s.state);
169         }
170     }
171     
172     /** Test enter from S mode to X mode *
173     public void testXtoS() {
174         State s = new State ();
175         
176         p.enterReadAccess ();
177         p.enterWriteAccess ();
178         s.run();
179         p.exitWriteAccess();
180         p.exitReadAccess();
181         if (s.state != 1) {
182             fail ("Run more times?: " + s.state);
183         }
184     }
185 */

186
187     /** Tests posting write and read requests while the Mutex is held
188      * in X mode and was entered in S mode as well
189      */

190     public void testPostWriteReadRequests() {
191         State s = new State ();
192         
193         // first enter
194
p.enterWriteAccess ();
195             p.enterReadAccess ();
196         
197             m.postWriteRequest(s);
198             
199             if (s.state != 0) {
200                 fail ("Write request started when we are in read access");
201             }
202                 
203             m.postReadRequest(s);
204             
205             if (s.state != 0) {
206                 fail ("Read request started when we are in write access");
207             }
208             
209             p.exitReadAccess ();
210             
211             if (s.state != 1) {
212                 fail ("Write request not run when leaving read access: " + s.state);
213             }
214             
215         // exiting
216
p.exitWriteAccess ();
217         
218         if (s.state != 2) {
219             fail ("Read request not run when leaving write access: " + s.state);
220         }
221         
222         consistencyCheck();
223     }
224        
225     /** Tests simple postWriteRequest */
226     public void testSimplePostWriteRequest() {
227         State s = new State ();
228         
229         m.postWriteRequest(s);
230         
231         if (s.state != 1) {
232             fail ("Write request not run: " + s.state);
233         }
234         
235         consistencyCheck();
236     }
237     
238     /** Tests simple postReadRequest */
239     public void testSimplePostReadRequest() {
240         State s = new State ();
241         
242         m.postReadRequest(s);
243         
244         if (s.state != 1) {
245             fail ("Read request not run: " + s.state);
246         }
247         
248         consistencyCheck();
249     }
250     
251     // starts a new thread, after return the thread will hold lock "p" in
252
// mode X for timeout milliseconds
253
private static void asyncEnter(final Mutex.Privileged p, final boolean X, final long timeout) throws InterruptedException JavaDoc {
254         asyncEnter(p, X, timeout, null);
255     }
256
257      // starts a new thread, after return the thread will hold lock "p" in
258
// mode X for timeout milliseconds, the new thread execs "run" first
259
private static void asyncEnter(final Mutex.Privileged p, final boolean X, final long timeout, final Runnable JavaDoc run) throws InterruptedException JavaDoc {
260         final Object JavaDoc lock = new Object JavaDoc();
261         
262         synchronized (lock) {
263             new Thread JavaDoc(new Runnable JavaDoc() {
264                 public void run() {
265                     if (X) {
266                         p.enterWriteAccess();
267                     } else {
268                         p.enterReadAccess();
269                     }
270                     
271                     synchronized (lock) {
272                         lock.notify();
273                     }
274                     
275                     if (run != null) {
276                         run.run();
277                     }
278                     
279                     try {
280                         Thread.sleep(timeout);
281                     } catch (InterruptedException JavaDoc e) {
282                         e.printStackTrace();
283                     }
284                     
285                     if (X) {
286                         p.exitWriteAccess();
287                     } else {
288                         p.exitReadAccess();
289                     }
290                     
291                 }
292             }).start();
293             
294             lock.wait();
295         }
296     }
297     
298     /** Tests enterWriteAccess while the Mutex is contended in X mode by
299      * another thread
300      */

301     public void testXContendedX() throws InterruptedException JavaDoc {
302         asyncEnter(p, true, 2000);
303         
304         // first enter
305
p.enterWriteAccess();
306         p.exitWriteAccess();
307         
308         consistencyCheck();
309     }
310     
311     /** Tests enterReadAccess while the Mutex is contended in X mode by
312      * another thread
313      */

314     public void testXContendedS() throws InterruptedException JavaDoc {
315         asyncEnter(p, true, 2000);
316         
317         // first enter
318
p.enterReadAccess();
319         p.exitReadAccess();
320         
321         consistencyCheck();
322     }
323     
324     /** Tests enterWriteAccess while the Mutex is contended in S mode by
325      * another thread
326      */

327     public void testSContendedX() throws InterruptedException JavaDoc {
328         asyncEnter(p, false, 2000);
329         
330         // first enter
331
p.enterWriteAccess();
332         p.exitWriteAccess();
333         
334         consistencyCheck();
335     }
336     
337     /** Tests enterReadAccess while the Mutex is contended in S mode by
338      * another thread
339      */

340     public void testSContendedS() throws InterruptedException JavaDoc {
341         asyncEnter(p, false, 2000);
342         
343         // first enter
344
p.enterReadAccess();
345         p.exitReadAccess();
346         
347         consistencyCheck();
348     }
349     
350     /** Tests postWriteRequest while the Mutex is contended in X mode by
351      * another thread
352      */

353     public void testXContendedPx() throws InterruptedException JavaDoc {
354         asyncEnter(p, true, 2000);
355         
356         State s = new State ();
357         
358         m.postWriteRequest(s);
359         
360         if (s.state != 1) {
361             fail ("Write request not run: " + s.state);
362         }
363         
364         consistencyCheck();
365     }
366     
367     /** Tests postReadRequest while the Mutex is contended in X mode by
368      * another thread
369      */

370     public void testXContendedPs() throws InterruptedException JavaDoc {
371         asyncEnter(p, true, 2000);
372         
373         State s = new State ();
374         
375         m.postReadRequest(s);
376         
377         if (s.state != 1) {
378             fail ("Read request not run: " + s.state);
379         }
380         
381         consistencyCheck();
382     }
383     
384     /** Tests postWriteRequest while the Mutex is contended in S mode by
385      * another thread
386      */

387     public void testSContendedPx() throws InterruptedException JavaDoc {
388         asyncEnter(p, false, 2000);
389         
390         State s = new State ();
391         
392         m.postWriteRequest(s);
393         
394         if (s.state != 1) {
395             fail ("Write request not run: " + s.state);
396         }
397         
398         consistencyCheck();
399     }
400     
401     /** Tests postReadRequest while the Mutex is contended in S mode by
402      * another thread
403      */

404     public void testSContendedPs() throws InterruptedException JavaDoc {
405         asyncEnter(p, false, 2000);
406         
407         State s = new State ();
408         
409         m.postReadRequest(s);
410         
411         if (s.state != 1) {
412             fail ("Write request not run: " + s.state);
413         }
414         
415         consistencyCheck();
416     }
417     
418     /** Tests postWriteRequest and postReadRequest while the Mutex is contended in S mode by
419      * another thread as well as this thread.
420      */

421     public void testSContendedSPsPx() throws InterruptedException JavaDoc {
422         asyncEnter(p, false, 2000);
423         
424         State s = new State ();
425         
426         p.enterReadAccess();
427         m.postReadRequest(s);
428         
429         if (s.state != 1) {
430             fail ("Read request not run: " + s.state);
431         }
432         
433         m.postWriteRequest(s);
434         
435         if (s.state != 1) {
436             fail ("Write request run: " + s.state);
437         }
438         
439         p.exitReadAccess();
440         
441         if (s.state != 2) {
442             fail ("Write request not run: " + s.state);
443         }
444         
445         consistencyCheck();
446     }
447     
448     /** The Mutex is held in S mode by a thread which also posted a
449      * write request. Another thread tries enterWriteAccess.
450      */

451     public void testSPxContendedX() throws Exception JavaDoc {
452         final State s = new State ();
453
454         asyncEnter(p, false, 2000, new Runnable JavaDoc() {
455             public void run() {
456                 try {
457                     Thread.sleep(1000);
458                 } catch (Exception JavaDoc e) {
459                     e.printStackTrace();
460                 }
461                 m.postWriteRequest(s);
462                 if (s.state == 1) {
463                     fail ("Write request run: " + s.state);
464                 }
465             }
466         });
467         
468         p.enterWriteAccess();
469         if (s.state != 1) {
470             fail ("Write request not run: " + s.state);
471         }
472         p.exitWriteAccess();
473         
474         consistencyCheck();
475     }
476     
477     /**
478      * Test case for #16577. Grab X,S and post X request,
479      * the second thread waits for X, causing the mutex to be
480      * in CHAINED.
481      */

482     public void testXSPxContendedX() throws Exception JavaDoc {
483         final State s = new State ();
484
485         asyncEnter(p, true, 2000, new Runnable JavaDoc() {
486             public void run() {
487                 p.enterReadAccess();
488                 try {
489                     Thread.sleep(1000);
490                 } catch (Exception JavaDoc e) {
491                     e.printStackTrace();
492                 }
493                 m.postWriteRequest(s);
494                 p.exitReadAccess();
495                 
496                 if (s.state != 1) {
497                     fail ("Write request not run: " + s.state);
498                 }
499             }
500         });
501         
502         p.enterWriteAccess();
503         p.exitWriteAccess();
504         
505         consistencyCheck();
506     }
507     
508     /**
509      * The scenario:
510      * Cast:
511      * Thread A: M.reader [X] trying to lock(L)
512      * Thread B: L owner [X] trying to enter M.read
513      * Thread C: M.reader trying to M.writeReenter on leave
514      *
515      * Actions:
516      * - first let A and B reach point [X]
517      * - unfuse A so it block on lock(L)
518      * - start C, it will reach exitReadAccess and block on reenter as writer
519      * - unfuse B so it should perform its legitimate read access
520      *
521      * What should happen then (if Mutex works OK):
522      * - B unlocks L and die
523      * - A locks/unlocks L, leave readAccess and die
524      * - C performs its write and die
525      */

526     public void testStarvation68106() throws Exception JavaDoc {
527         final Mutex.Privileged PR = new Mutex.Privileged();
528         final Mutex M = new Mutex(PR);
529         final Object JavaDoc L = new Object JavaDoc();
530         final boolean[] done = new boolean[3];
531         
532         final Ticker tickX1 = new Ticker();
533         final Ticker tickX2 = new Ticker();
534         final Ticker tickX3 = new Ticker();
535         
536         Thread JavaDoc A = new Thread JavaDoc("A") { public void run() {
537             PR.enterReadAccess();
538             
539             tickX1.tick();
540             tickX2.waitOn();
541             
542             synchronized(L) {
543                 done[0] = true;
544             }
545
546             PR.exitReadAccess();
547         }};
548                
549         Thread JavaDoc B = new Thread JavaDoc("B") { public void run() {
550             synchronized(L) {
551                 
552                 tickX2.tick();
553                 tickX3.tick();
554                 tickX1.waitOn();
555                 
556                 PR.enterReadAccess();
557                 done[1] = true;
558                 PR.exitReadAccess();
559             }
560         }};
561
562         Thread JavaDoc C = new Thread JavaDoc("C") { public void run() {
563             PR.enterReadAccess();
564             M.postWriteRequest(new Runnable JavaDoc() {public void run() {
565                    done[2] = true;
566             }});
567             PR.exitReadAccess();
568         }};
569         
570         A.start();
571         tickX1.waitOn();
572         // A reached point X
573

574         B.start();
575         tickX3.waitOn();
576         // B reached point X, unlocked A so in would block on lock(L)
577

578         C.start();
579     Thread.sleep(100); // wait for C to perform exitReadAccess (can't
580
// tick as it will block in case of failure...)
581

582         tickX1.tick();
583         // push B, everything should finish after this
584

585         // wait for them for a while
586
A.join(2000);
587         B.join(2000);
588         C.join(2000);
589
590         if (!done[0] || !done[1] || !done[2]) {
591             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
592             sb.append("A: "); sb.append(done[0]);
593             sb.append(" B: "); sb.append(done[1]);
594             sb.append(" C: "); sb.append(done[2]);
595             sb.append("\n");
596             dumpStrackTrace(A, sb);
597             dumpStrackTrace(B, sb);
598             dumpStrackTrace(C, sb);
599
600             fail(sb.toString());
601         }
602     }
603
604     
605     /**
606      * The scenario:
607      * - Have 3 threads, A, B and C
608      * - writeLock mutex1 in A
609      * - writeLock mutex2 in B
610      * - postReadLock mutex2 in B
611      * - writeLock mutex1 in B
612      * - writeLock mutex2 in C
613      * - readLock mutex2 in A
614      * - leaveWriteLock mutex2 in B
615      *
616      */

617     public void testStarvation49466() throws Exception JavaDoc {
618         final Mutex.Privileged pr1 = new Mutex.Privileged();
619         final Mutex mutex1 = new Mutex(pr1);
620         
621         final Mutex.Privileged pr2 = new Mutex.Privileged();
622         final Mutex mutex2 = new Mutex(pr2);
623         
624         final boolean[] done = new boolean[3];
625
626         final Ticker tick0 = new Ticker();
627         final Ticker tick1 = new Ticker();
628         final Ticker tick2 = new Ticker();
629         final Ticker tick3 = new Ticker();
630         
631         Thread JavaDoc A = new Thread JavaDoc() {
632             public void run() {
633                 pr1.enterWriteAccess();
634                 tick0.tick();
635                 
636                 tick1.waitOn();
637                 
638                 pr2.enterReadAccess();
639                 done[0] = true;
640                 pr2.exitReadAccess();
641                     
642                 pr1.exitWriteAccess();
643             }
644         };
645
646         // writeLock mutex1 in A
647
A.start();
648         tick0.waitOn();
649
650         
651         Thread JavaDoc B = new Thread JavaDoc() {
652             public void run() {
653                 pr2.enterWriteAccess();
654                 
655                 mutex2.postReadRequest(new Runnable JavaDoc() {
656                    public void run() {
657                        tick0.tick();
658                        pr1.enterWriteAccess();
659                        done[1] = true;
660                        pr1.exitWriteAccess();
661                    }
662                 });
663
664                 tick0.tick();
665                 
666                 tick2.waitOn();
667                 
668                 pr2.exitWriteAccess();
669             }
670         };
671         
672         // writeLock mutex2 in B
673
B.start();
674         tick0.waitOn();
675
676 /*
677  * The test fails even when using only first two threads.
678  *
679         Thread C = new Thread() {
680             public void run() {
681                 tick0.tick(); // have to tick in advance and wait :-(
682                 pr2.enterWriteAccess();
683                 done[2] = true;
684                 pr2.exitWriteAccess();
685             }
686         };
687         
688         // writeLock mutex2 in C
689         C.start();
690         tick0.waitOn();
691         Thread.sleep(1000); // between tick and C enqueued ...
692 */

693         
694         // readLock mutex2 in A
695
tick1.tick(); // enqueues A in mutex2's queue
696
Thread.sleep(1000); // between tick and A enqueued ...
697

698         // leaveWriteLock mutex2 in B
699
tick2.tick();
700         
701         // postReadLock mutex2 in B
702
tick0.waitOn();
703
704         // System.err.println("Do a thread dump now!");
705
Thread.sleep(2000); // give them some time ...
706

707         assertTrue("Thread A finished", done[0]);
708         assertTrue("Thread B finished", done[1]);
709         
710 // assertTrue("Thread C succeed", done[2]);
711
}
712
713     
714     public void testReadEnterAfterPostWriteWasContended87932() throws Exception JavaDoc {
715         final Logger JavaDoc LOG = Logger.getLogger("org.openide.util.test");//testReadEnterAfterPostWriteWasContended87932");
716

717         final Mutex.Privileged pr = new Mutex.Privileged();
718         final Mutex mutex = new Mutex(pr);
719         final Ticker tick = new Ticker();
720         final AtomicBoolean JavaDoc inWrite = new AtomicBoolean JavaDoc();
721         
722         Thread JavaDoc t = new Thread JavaDoc("testReadEnterAfterPostWriteWasContended87932-reader") {
723             public void run() {
724                 pr.enterReadAccess();
725                 tick.tick();
726                 
727                 // wait for exploitable place in Mutex
728
LOG.log(Level.FINE, "wait for exploitable place in Mutex");
729
730                 pr.exitReadAccess();
731                 
732                 //Let the othe thread continue
733
LOG.log(Level.FINE, "Let the other thread continue");
734                 
735                 // the writer gets in now, lets' give him some time.
736
MutexTest.sleep(50);
737                 pr.enterReadAccess();
738 // if (inWrite.get()) fail("Another reader inside while writer keeps lock");
739
pr.exitReadAccess();
740                 
741                 
742             }
743         };
744         String JavaDoc str = "THREAD:testReadEnterAfterPostWriteWasContended87932-reader MSG:wait for exploitable place in Mutex" +
745                 "THREAD:main MSG:.*Processing posted requests: 2" +
746                 "THREAD:testReadEnterAfterPostWriteWasContended87932-reader MSG:Let the other thread continue";
747         Log.controlFlow(Logger.getLogger("org.openide.util"), null, str, 100);
748         
749         pr.enterReadAccess();
750         t.start();
751         
752         tick.waitOn();
753         mutex.postWriteRequest(new Runnable JavaDoc() {
754             public void run() {
755                 inWrite.set(true);
756                 // just keep the write lock for a while
757
sleep(1000);
758                 inWrite.set(false);
759             }
760         });
761         pr.exitReadAccess();
762         
763         t.join(10000);
764     }
765     
766     private static class Ticker {
767         boolean state;
768         
769         public void waitOn() {
770             synchronized(this) {
771                 while (!state) {
772                     try {
773                         wait();
774                     } catch (InterruptedException JavaDoc e) {
775                         throw new InternalError JavaDoc();
776                     }
777                 }
778                 state = false; // reusable
779
}
780         }
781         
782         public void tick() {
783             synchronized(this) {
784                 state = true;
785                 notifyAll();
786             }
787         }
788     }
789     
790     
791     
792     /**
793      * Grab X and post S request,
794      * the second thread waits for X, causing the mutex to be
795      * in CHAINED.
796      */

797     public void testXPsContendedX() throws Exception JavaDoc {
798         final State s = new State ();
799
800         asyncEnter(p, true, 2000, new Runnable JavaDoc() {
801             public void run() {
802                 try {
803                     Thread.sleep(1000);
804                 } catch (Exception JavaDoc e) {
805                     e.printStackTrace();
806                 }
807                 m.postReadRequest(s);
808                 
809                 if (s.state == 1) {
810                     fail ("Read request run: " + s.state);
811                 }
812             }
813         });
814         
815         p.enterWriteAccess();
816         Thread.sleep(4000);
817         p.exitWriteAccess();
818         
819         consistencyCheck();
820     }
821     
822     /** Checks the Mutex is in the consistent state, i.e. enterWriteAccess must pass */
823     private void consistencyCheck() {
824         p.enterWriteAccess();
825         p.exitWriteAccess();
826     }
827     
828     public void testNoWayToDoReadAndThenWrite () {
829         class R implements Runnable JavaDoc {
830             public void run () {
831                 m.writeAccess (this);
832             }
833         }
834         
835         try {
836             m.readAccess (new R ());
837             fail ("This is supposed to throw an IllegalStateException");
838         } catch (IllegalStateException JavaDoc ex) {
839             // ok, this is expected
840
}
841     }
842
843     public void testNoWayToDoWriteThenReadAndThenWrite () {
844         class R implements Runnable JavaDoc {
845             public boolean second;
846             public boolean end;
847             public boolean ending;
848             
849             public void run () {
850                 if (end) {
851                     ending = true;
852                     return;
853                 }
854                 
855                 if (second) {
856                     end = true;
857                     m.writeAccess (this);
858                 } else {
859                     second = true;
860                     m.readAccess (this);
861                 }
862             }
863         }
864         R r = new R ();
865         try {
866             m.writeAccess (r);
867             fail ("This is supposed to throw an IllegalStateException");
868         } catch (IllegalStateException JavaDoc ex) {
869             // ok, this is expected
870
assertTrue ("We were in the write access section", r.second);
871             assertTrue ("We were before the writeAcess(this)", r.end);
872             assertFalse ("We never reached ending", r.ending);
873         }
874     }
875     
876     public void testIsOrIsNotInReadOrWriteAccess () {
877         new ReadWriteChecking ("No r/w", Boolean.FALSE, Boolean.FALSE).run ();
878         m.readAccess (new ReadWriteChecking ("r but no w", Boolean.TRUE, Boolean.FALSE));
879         m.writeAccess (new ReadWriteChecking ("w but no r", Boolean.FALSE, Boolean.TRUE));
880         m.readAccess (new Runnable JavaDoc () {
881             public void run () {
882                 m.postReadRequest (new ReadWriteChecking ("+r -w", Boolean.TRUE, Boolean.FALSE));
883             }
884         });
885         m.readAccess (new Runnable JavaDoc () {
886             public void run () {
887                 m.postWriteRequest (new ReadWriteChecking ("-r +w", Boolean.FALSE, Boolean.TRUE));
888             }
889         });
890         m.writeAccess (new Runnable JavaDoc () {
891             public void run () {
892                 m.postReadRequest (new ReadWriteChecking ("+r -w", Boolean.TRUE, Boolean.FALSE));
893             }
894         });
895         m.writeAccess (new Runnable JavaDoc () {
896             public void run () {
897                 m.postWriteRequest (new ReadWriteChecking ("-r +w", Boolean.FALSE, Boolean.TRUE));
898             }
899         });
900         
901         // write->read->test (downgrade from write to read)
902
m.writeAccess (new Runnable JavaDoc () {
903             public boolean second;
904             
905             public void run () {
906                 if (!second) {
907                     second = true;
908                     m.readAccess (this);
909                     return;
910                 }
911                 
912                 class P implements Runnable JavaDoc {
913                     public boolean exec;
914                     public void run () {
915                         exec = true;
916                     }
917                 }
918                 P r = new P ();
919                 P w = new P ();
920                 m.postWriteRequest (w);
921                 m.postReadRequest (r);
922                 assertFalse ("Writer not executed", w.exec);
923                 assertFalse ("Reader not executed", r.exec);
924                 
925                 m.readAccess (new ReadWriteChecking ("+r +w", Boolean.TRUE, Boolean.TRUE));
926             }
927         });
928         
929         new ReadWriteChecking ("None at the end", Boolean.FALSE, Boolean.FALSE).run ();
930     }
931
932     // [pnejedly:] There was an attempt to fix Starvation68106 by allowing read
933
// enter while Mutex is currently in CHAIN mode, but that's wrong, as it can
934
// be CHAIN/W (write granted, readers waiting). Let's cover this with a test.
935
public void testReaderCannotEnterWriteChainedMutex() throws Exception JavaDoc {
936         final Mutex.Privileged PR = new Mutex.Privileged();
937         final Mutex M = new Mutex(PR);
938         final boolean[] done = new boolean[2];
939         
940         final Ticker tickX1 = new Ticker();
941         final Ticker tickX2 = new Ticker();
942         final Ticker tickX3 = new Ticker();
943         
944         PR.enterWriteAccess();
945         
946         Thread JavaDoc A = new Thread JavaDoc("A") { public void run() {
947             PR.enterReadAccess();
948             done[0] = true;
949             PR.exitReadAccess();
950         }};
951                
952         Thread JavaDoc B = new Thread JavaDoc("B") { public void run() {
953             PR.enterReadAccess();
954             done[1] = true;
955             PR.exitReadAccess();
956         }};
957
958         A.start();
959         Thread.sleep(100); // wait for A to chain in M
960

961         B.start();
962         Thread.sleep(100);; // B should chain as well
963

964         assertFalse ("B should chain-wait", done[1]);
965         
966         // final cleanup and consistency check:
967
PR.exitWriteAccess();
968         A.join(1000);
969         B.join(1000);
970         assertTrue("A finished after unblocking M", done[0]);
971         assertTrue("B finished after unblocking M", done[1]);
972     }
973     
974     public void testIsReadOrWriteForEventMutex () throws Exception JavaDoc {
975         class DoTheWork implements Runnable JavaDoc {
976             public boolean isRead;
977             public boolean isWrite;
978             
979             public void run () {
980                 isRead = Mutex.EVENT.isReadAccess ();
981                 isWrite = Mutex.EVENT.isWriteAccess ();
982             }
983         }
984         
985         DoTheWork rp = new DoTheWork ();
986         org.openide.util.RequestProcessor.getDefault ().post(rp).waitFinished ();
987         
988         DoTheWork awt = new DoTheWork ();
989         javax.swing.SwingUtilities.invokeAndWait (awt);
990         
991         assertFalse ("Nothing in RP", rp.isRead);
992         assertFalse ("No in RP", rp.isWrite);
993         
994         assertTrue ("Is read in ", awt.isRead);
995         assertTrue ("is also write", awt.isWrite);
996     }
997
998     private void exceptionsReporting(final Throwable JavaDoc t) throws Exception JavaDoc {
999         final IOException JavaDoc e1 = new IOException JavaDoc();
1000        final Mutex mm = m;
1001        final Runnable JavaDoc secondRequest = new Runnable JavaDoc() {
1002            public void run() {
1003                if (t instanceof RuntimeException JavaDoc) {
1004                    throw (RuntimeException JavaDoc)t;
1005                } else {
1006                    throw (Error JavaDoc)t;
1007                }
1008            }
1009        };
1010        Mutex.ExceptionAction<Object JavaDoc> firstRequest = new Mutex.ExceptionAction<Object JavaDoc>() {
1011            public Object JavaDoc run () throws Exception JavaDoc {
1012                mm.postWriteRequest(secondRequest);
1013                throw e1;
1014            }
1015        };
1016        try {
1017            m.readAccess(firstRequest);
1018        } catch (MutexException mu) {
1019            Exception JavaDoc e = mu.getException();
1020            assertEquals("IOException correctly reported", e, e1);
1021            return;
1022        } catch (Throwable JavaDoc e) {
1023            fail("a problem in postWriteRequest() should not swallow any " +
1024                    "exception thrown in readAccess() because that might be " +
1025                    "the cause of the problem. "+e.toString());
1026        }
1027        fail("should never get here");
1028    }
1029
1030    public void testThrowingAssertionErrorInSpecialCase() throws Exception JavaDoc {
1031        exceptionsReporting(new AssertionError JavaDoc());
1032    }
1033    
1034    public void testThrowingRuntimeExceptionInSpecialCase() throws Exception JavaDoc {
1035        exceptionsReporting(new RuntimeException JavaDoc());
1036    }
1037
1038    private void dumpStrackTrace(Thread JavaDoc thread, StringBuffer JavaDoc sb) throws IllegalAccessException JavaDoc, InvocationTargetException JavaDoc {
1039        sb.append("StackTrace for thread: " + thread.getName() + "\n");
1040
1041        StackTraceElement JavaDoc[] arr = thread.getStackTrace();
1042
1043        for (int i = 0; i < arr.length; i++) {
1044            sb.append(arr[i].toString());
1045            sb.append("\n");
1046        }
1047    }
1048    
1049    private class ReadWriteChecking implements Runnable JavaDoc {
1050        public Boolean JavaDoc read;
1051        public Boolean JavaDoc write;
1052        public String JavaDoc msg;
1053
1054        public ReadWriteChecking (String JavaDoc msg, Boolean JavaDoc read, Boolean JavaDoc write) {
1055            assertNotNull ("Msg cannot be null", msg);
1056            this.msg = msg;
1057            this.read = read;
1058            this.write = write;
1059        }
1060
1061        protected void finalize () {
1062            assertNull ("Run method was not called!", msg);
1063        }
1064
1065        public void run () {
1066            if (write != null) assertEquals (msg, write.booleanValue (), m.isWriteAccess ());
1067            if (read != null) assertEquals (msg, read.booleanValue (), m.isReadAccess ());
1068            msg = null;
1069        }
1070    }
1071    
1072    
1073    private static class State implements Runnable JavaDoc {
1074        public int state;
1075
1076        public void run () {
1077            state++;
1078        }
1079        
1080    } // end of State
1081

1082    private static final void sleep(long ms) {
1083        try {
1084            Thread.sleep(ms);
1085        } catch (InterruptedException JavaDoc ex) {
1086            ex.printStackTrace();
1087        }
1088    }
1089
1090    protected Level JavaDoc logLevel() {
1091        return Level.FINEST;
1092    }
1093}
1094
Popular Tags