This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 16849
Collapse All | Expand All

(-)src/org/openide/util/RequestProcessor.java (+35 lines)
Lines 447-452 Link Here
447
                super.waitFinished ();
447
                super.waitFinished ();
448
            }
448
            }
449
        }
449
        }
450
        
451
        /** Enhanced reimplementation of the {@link Task#waitFinished(long)}
452
        * method. The added semantic is that if one calls this method from
453
        * another task of the same processor, and the task has not yet been
454
        * executed, the method will immediatelly detect that and throw
455
        * <code>InterruptedException</code> to signal that state.
456
        * 
457
        * @param timeout the amount of time to wait
458
        * @exception InterruptedException if waiting has been interrupted or if
459
        *    the wait cannot succeed due to possible deadlock collision
460
        * @return true if the task was finished successfully during the
461
        *    timeout period, false otherwise
462
        *  @since JST-PENDING
463
        */
464
        public boolean waitFinished (long timeout) throws InterruptedException {
465
            if (isRequestProcessorThread()) {
466
                boolean toRun;
467
468
                synchronized (processorLock) {
469
                    toRun = !isFinished () && (item == null || item.clear ());
470
                }
471
472
                if (toRun) { 
473
                    throw new InterruptedException ("Cannot wait with timeout " + timeout + " from the RequestProcessor thread for task: " + this); // NOI18N
474
                } else { // it is already running in other thread of this RP
475
                    if (lastThread != Thread.currentThread()) {
476
                        return super.waitFinished (timeout);
477
        		    } else {
478
                        return true;
479
                    }
480
                }
481
            } else {
482
                return super.waitFinished (timeout);
483
            }
484
        }
450
485
451
        public String toString () {
486
        public String toString () {
452
            return "RequestProcessor.Task [" + name  + ", " + priority + "] for " + super.toString(); // NOI18N
487
            return "RequestProcessor.Task [" + name  + ", " + priority + "] for " + super.toString(); // NOI18N
(-)src/org/openide/util/Task.java (-1 / +86 lines)
Lines 41-46 Link Here
41
    static {
41
    static {
42
        EMPTY.finished = true;
42
        EMPTY.finished = true;
43
    }
43
    }
44
    /** map of subclasses to booleans whether they override waitFinished() or not 
45
     * <Class, Boolean>
46
     */
47
    private static java.util.WeakHashMap overrides;
48
    /** request processor for workarounding compatibility problem with
49
     * classes that do not override waitFinished (long)
50
     */
51
    private static RequestProcessor RP;
44
52
45
    /** what to run */
53
    /** what to run */
46
    private Runnable run;
54
    private Runnable run;
Lines 89-94 Link Here
89
        }
97
        }
90
    }
98
    }
91
99
100
101
    /** Wait until the task is finished, but only a given time.
102
    *  @param milliseconds time in milliseconds to wait for the result
103
    *  @exception InterruptedException when the waiting has been interrupted
104
    *  @return true if the task is really finished, or false if the time out
105
    *     has been exceeded
106
    *  @since JST-PENDING
107
    */
108
    public boolean waitFinished (long milliseconds) throws InterruptedException {
109
        synchronized (this) {
110
            if (overridesTimeoutedWaitFinished ()) {
111
                // the the task overrides waitFinished (timeout) or is 
112
                // one of the basic tasks, then we can just simply do our bese
113
                // code. Otherwise we have to execute threading workaround
114
                if (finished) return true;
115
                
116
                long expectedEnd = System.currentTimeMillis () + milliseconds;
117
                for (;;) {
118
                    wait (milliseconds);
119
                    
120
                    if (finished) return true;
121
                    long now = System.currentTimeMillis ();
122
                    
123
                    if (expectedEnd <= now) return false;
124
                    
125
                    milliseconds = expectedEnd - now;
126
                }
127
            }
128
        }
129
        
130
        
131
        // as we know that RequestProcessor implements the waitFinished(long)
132
        // correctly we just post a task for waitFinished() into some
133
        // of its threads and wait just the given milliseconds time
134
        // for the result, by that we can guarantee the semantics
135
        // of the call
136
        class Run implements Runnable {
137
            public void run () {
138
                Task.this.waitFinished ();
139
            }
140
        }
141
        RequestProcessor.Task task = RP.post (new Run ());
142
        return task.waitFinished (milliseconds);
143
    }
144
    
92
    /** Changes the state of the task to be running. Any call after this
145
    /** Changes the state of the task to be running. Any call after this
93
    * one and before notifyFinished to waitFinished blocks.
146
    * one and before notifyFinished to waitFinished blocks.
94
    * @since 1.5
147
    * @since 1.5
Lines 157-165 Link Here
157
        if (list == null) return;
210
        if (list == null) return;
158
        list.remove (l);
211
        list.remove (l);
159
    }
212
    }
160
213
    
161
    public String toString () {
214
    public String toString () {
162
        return "task " + run; // NOI18N
215
        return "task " + run; // NOI18N
216
    }
217
    
218
    /** Checks whether the class overrides wait finished.
219
     */
220
    private boolean overridesTimeoutedWaitFinished () {
221
        // yes we implement it corretly
222
        if (getClass () == Task.class) return true;
223
        // RequestProcessor.Task overrides correctly
224
        if (getClass () == RequestProcessor.Task.class) return true;
225
        
226
        java.util.WeakHashMap m;
227
        Boolean does;
228
        synchronized (Task.class) {
229
            if (overrides == null) {
230
                overrides = new java.util.WeakHashMap ();
231
                RP = new RequestProcessor ("Timeout waitFinished compatibility processor", 255); // NOI18N
232
            }
233
            m = overrides;
234
            
235
            does = (Boolean)m.get (getClass ());
236
            if (does != null) return does.booleanValue ();
237
            
238
            try {
239
                java.lang.reflect.Method method = getClass ().getMethod ("waitFinished", new Class[] { Long.TYPE }); // NOI18N
240
                does = Boolean.valueOf (method.getDeclaringClass () != Task.class);
241
                m.put (getClass (), does);
242
                return does.booleanValue ();
243
            } catch (Exception ex) {
244
                org.openide.ErrorManager.getDefault ().notify (ex);
245
                return true;
246
            }
247
        }
163
    }
248
    }
164
    
249
    
165
    /** Reveal the identity of the worker runnable.
250
    /** Reveal the identity of the worker runnable.
(-)test/unit/src/org/openide/util/RequestProcessorTest.java (+83 lines)
Lines 564-569 Link Here
564
        assertTrue("Task was performed even if it is canceled", !x.performed);
564
        assertTrue("Task was performed even if it is canceled", !x.performed);
565
    }
565
    }
566
    
566
    
567
    public void testWaitWithTimeOutCanFinishEvenTheTaskHasNotRun () throws Exception {
568
        class Run implements Runnable {
569
            public boolean runned;
570
            public synchronized void run () {
571
                runned = true;
572
            }
573
        }
574
        
575
        Run run = new Run ();
576
        
577
        synchronized (run) {
578
            RequestProcessor.Task task = RequestProcessor.getDefault ().post (run);
579
            task.waitFinished (100);
580
            assertFalse ("We are here and the task has not finished", run.runned);
581
            assertFalse ("Not finished", task.isFinished ());
582
        }
583
    }
584
    
585
    public void testWhenWaitingForALimitedTimeFromTheSameProcessorThenInterruptedExceptionIsThrownImmediatelly () throws Exception {
586
        Counter x = new Counter ();
587
        RequestProcessor rp = new RequestProcessor ("testWaitFinishedOnNotStartedTaskFromRPThread");
588
        final RequestProcessor.Task task = rp.create (x);
589
        
590
        class WaitTask implements Runnable {
591
            public boolean finished;
592
            
593
            public synchronized void run () {
594
                long time = System.currentTimeMillis ();
595
                try {
596
                    task.waitFinished (1000);
597
                    fail ("This should throw an exception. Btw time was: " + (System.currentTimeMillis () - time));
598
                } catch (InterruptedException ex) {
599
                    // ok, this is expected
600
                } finally {
601
                    time = System.currentTimeMillis () - time;
602
                    notifyAll ();
603
                }
604
                if (time > 100) {
605
                    fail ("Exception should be thrown quickly. Was: " + time);
606
                }
607
                finished = true;
608
            }
609
            
610
        }
611
        WaitTask wt = new WaitTask ();
612
        synchronized (wt) {
613
            rp.post (wt);
614
            wt.wait ();
615
        }
616
        assertTrue ("The task.waitFinished has to finish", wt.finished);
617
        x.assertCnt ("The task has NOT been executed", 0);
618
    }
619
    
620
    public void testWhenWaitingForAlreadyFinishedTaskWithTimeOutTheResultIsGood () throws Exception {
621
        Counter x = new Counter ();
622
        RequestProcessor rp = new RequestProcessor ("testWaitFinishedOnStartedTaskFromRPThread");
623
        final RequestProcessor.Task task = rp.post (x);
624
        task.waitFinished ();
625
        x.assertCnt ("The task has been executed before", 1);
626
        
627
        class WaitTask implements Runnable {
628
            public boolean finished;
629
            
630
            public synchronized void run () {
631
                notifyAll ();
632
                try {
633
                    assertTrue ("The task has been already finished", task.waitFinished (1000));
634
                } catch (InterruptedException ex) {
635
                    ex.printStackTrace();
636
                    fail ("Should not happen");
637
                }
638
                finished = true;
639
            }
640
            
641
        }
642
        WaitTask wt = new WaitTask ();
643
        synchronized (wt) {
644
            rp.post (wt);
645
            wt.wait ();
646
        }
647
        assertTrue ("The task.waitFinished has to finish", wt.finished);
648
    }
649
    
567
    private static void doGc (int count, Reference toClear) {
650
    private static void doGc (int count, Reference toClear) {
568
        java.util.ArrayList l = new java.util.ArrayList (count);
651
        java.util.ArrayList l = new java.util.ArrayList (count);
569
        while (count-- > 0) {
652
        while (count-- > 0) {
(-)test/unit/src/org/openide/util/TaskTest.java (-12 / +74 lines)
Lines 30-48 Link Here
30
    public static void main(java.lang.String[] args) {
30
    public static void main(java.lang.String[] args) {
31
        TestRunner.run(new NbTestSuite(TaskTest.class));
31
        TestRunner.run(new NbTestSuite(TaskTest.class));
32
    }
32
    }
33
33
    
34
    
35
    //
36
    // tests
37
    //
34
    public void testPlainTaskWaitsForBeingExecuted () throws Exception {
38
    public void testPlainTaskWaitsForBeingExecuted () throws Exception {
35
        class R implements Runnable {
36
            public synchronized void run () {
37
                notify ();
38
                try {
39
                    wait ();
40
                } catch (InterruptedException ex) {
41
                    ex.printStackTrace();
42
                }
43
            }
44
        }
45
        
46
        R run = new R ();
39
        R run = new R ();
47
        Task t = new Task (run);
40
        Task t = new Task (run);
48
        
41
        
Lines 68-72 Link Here
68
    public void testWaitFinishedOnEMPTYTaskReturnsImmediatelly () throws Exception {
61
    public void testWaitFinishedOnEMPTYTaskReturnsImmediatelly () throws Exception {
69
        Task.EMPTY.waitFinished ();
62
        Task.EMPTY.waitFinished ();
70
    }
63
    }
64
65
    public void testWaitWithTimeOutReturnsImmediatellyOnFinishedTasks () throws Exception {
66
        assertTrue ("Was successfully finished", Task.EMPTY.waitFinished (0));
67
    }
71
    
68
    
69
    public void testWaitWithTimeOutReturnsAfterTimeOutWhenTheTaskIsNotComputedAtAll () throws Exception {
70
        long time = System.currentTimeMillis ();
71
        Task t = new Task (new R ());
72
        t.waitFinished (1000);
73
        time = System.currentTimeMillis () - time;
74
        
75
        assertFalse ("Still not finished", t.isFinished ());
76
        
77
        if (time < 900 || time > 1100) {
78
            fail ("Something wrong happened the task should wait for 1000ms but it took: " + time);
79
        }
80
    }
81
    
82
    public void testWaitOnStrangeTaskThatStartsItsExecutionInOverridenWaitFinishedMethodLikeFolderInstancesDo () throws Exception {
83
        class MyTask extends Task {
84
            private int values;
85
            
86
            public MyTask () {
87
                notifyFinished ();
88
            }
89
            
90
            public void waitFinished () {
91
                notifyRunning ();
92
                values++;
93
                notifyFinished ();
94
            }
95
        }
96
        
97
        MyTask my = new MyTask ();
98
        assertTrue ("The task thinks that he is finished", my.isFinished ());
99
        assertTrue ("Ok, even with timeout we got the result", my.waitFinished (1000));
100
        assertEquals ("But the old waitFinished is called", 1, my.values);
101
    }
102
    
103
    public void testWaitOnStrangeTaskThatTakesReallyLongTime () throws Exception {
104
        class MyTask extends Task {
105
            public MyTask () {
106
                notifyFinished ();
107
            }
108
            
109
            public void waitFinished () {
110
                try {
111
                    Thread.sleep (5000);
112
                } catch (InterruptedException ex) {
113
                    fail ("Should not happen");
114
                }
115
            }
116
        }
117
        
118
        MyTask my = new MyTask ();
119
        assertTrue ("The task thinks that he is finished", my.isFinished ());
120
        assertFalse ("but still it get's called, but timeouts", my.waitFinished (1000));
121
    }
122
    
123
    final class R implements Runnable {
124
        public synchronized void run () {
125
            notify ();
126
            try {
127
                wait ();
128
            } catch (InterruptedException ex) {
129
                ex.printStackTrace();
130
            }
131
        }
132
    }
133
72
}
134
}

Return to bug 16849