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 123832
Collapse All | Expand All

(-)apichanges.xml (+18 lines)
Lines 49-54 Link Here
49
    <apidef name="actions">Actions API</apidef>
49
    <apidef name="actions">Actions API</apidef>
50
</apidefs>
50
</apidefs>
51
<changes>
51
<changes>
52
    <change id="Mutex.Wrapper">
53
        <api name="util"/>
54
        <summary>Mutex made pluggable</summary>
55
        <version major="7" minor="10"/>
56
        <date day="7" month="1" year="2008"/>
57
        <author login="mkubec"/>
58
        <compatibility addition="yes"/>
59
        <description>
60
            <p>
61
                Added new constructor
62
                <a href="@TOP@/org/openide/util/Mutex.html">Mutex(Priviledged, Executor)</a>
63
                that allows creators of the mutex to intercept and wrap posted actions
64
                with custom code.
65
            </p>
66
        </description> 
67
        <class package="org.openide.util" name="Mutex"/>
68
        <issue number="123832"/>
69
    </change>
52
    <change id="Utilities.isLargeFrameIcons">
70
    <change id="Utilities.isLargeFrameIcons">
53
        <api name="util"/>
71
        <api name="util"/>
54
        <summary>Obsolete method <code>Utilities.isLargeFrameIcons</code> deprecated.</summary>
72
        <summary>Obsolete method <code>Utilities.isLargeFrameIcons</code> deprecated.</summary>
(-)nbproject/project.properties (-1 / +1 lines)
Lines 41-47 Link Here
41
javac.source=1.5
41
javac.source=1.5
42
module.jar.dir=lib
42
module.jar.dir=lib
43
43
44
spec.version.base=7.11.0
44
spec.version.base=7.12.0
45
45
46
# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
46
# For XMLSerializer, needed for XMLUtil.write to work w/ namespaces under JDK 1.4:
47
47
(-)src/org/openide/util/Mutex.java (-8 / +135 lines)
Lines 48-53 Link Here
48
import java.util.LinkedList;
48
import java.util.LinkedList;
49
import java.util.List;
49
import java.util.List;
50
import java.util.Map;
50
import java.util.Map;
51
import java.util.concurrent.Executor;
51
import java.util.logging.Level;
52
import java.util.logging.Level;
52
import java.util.logging.Logger;
53
import java.util.logging.Logger;
53
54
Lines 175-180 Link Here
175
176
176
    /** protects internal data structures */
177
    /** protects internal data structures */
177
    private /*final*/ Object LOCK;
178
    private /*final*/ Object LOCK;
179
    
180
    /** wrapper, if any */
181
    private final Executor wrapper;
178
182
179
    /** threads that - owns or waits for this mutex */
183
    /** threads that - owns or waits for this mutex */
180
    private /*final*/ Map<Thread,ThreadInfo> registeredThreads;
184
    private /*final*/ Map<Thread,ThreadInfo> registeredThreads;
Lines 200-211 Link Here
200
    */
204
    */
201
    public Mutex(Object lock) {
205
    public Mutex(Object lock) {
202
        init(lock);
206
        init(lock);
207
        this.wrapper = null;
203
    }
208
    }
204
209
205
    /** Default constructor.
210
    /** Default constructor.
206
    */
211
    */
207
    public Mutex() {
212
    public Mutex() {
208
        init(new InternalLock());
213
        init(new InternalLock());
214
        this.wrapper = null;
209
    }
215
    }
210
216
211
    /** @param privileged can enter privileged states of this Mutex
217
    /** @param privileged can enter privileged states of this Mutex
Lines 218-223 Link Here
218
            init(new InternalLock());
224
            init(new InternalLock());
219
            privileged.setParent(this);
225
            privileged.setParent(this);
220
        }
226
        }
227
        this.wrapper = null;
228
    }
229
230
    /** Constructor for those who wish to do some custom additional tasks
231
     * whenever an action or runnable is executed in the {@link Mutex}. This
232
     * may be useful for wrapping all the actions with custom {@link ThreadLocal}
233
     * value, etc. Just implement the {@link Executor}'s <code>execute(Runnable)</code>
234
     * method and do pre and post initialization tasks before running the runnable.
235
     * <p>
236
     * The {@link Executor#execute} method shall return only when the passed in
237
     * {@link Runnable} is finished, otherwise methods like {@link Mutex#readAccess(Action)} and co.
238
     * might not return proper result.
239
     * 
240
     * @param privileged can enter privileged states of this Mutex
241
     *  @param executor allows to wrap the work of the mutex with a custom code
242
     * @since 7.12
243
     */
244
    public Mutex(Privileged privileged, Executor executor) {
245
        LOCK = new Mutex(privileged);
246
        this.wrapper = executor;
221
    }
247
    }
222
248
223
    /** Initiates this Mutex */
249
    /** Initiates this Mutex */
Lines 236-242 Link Here
236
    * @param action the action to perform
262
    * @param action the action to perform
237
    * @return the object returned from {@link Mutex.Action#run}
263
    * @return the object returned from {@link Mutex.Action#run}
238
    */
264
    */
239
    public <T> T readAccess(Action<T> action) {
265
    public <T> T readAccess(final Action<T> action) {
240
        if (this == EVENT) {
266
        if (this == EVENT) {
241
            try {
267
            try {
242
                return doEventAccess(action);
268
                return doEventAccess(action);
Lines 244-249 Link Here
244
                throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N
270
                throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N
245
            }
271
            }
246
        }
272
        }
273
        if (wrapper != null) {
274
            try {
275
                return doWrapperAccess(action, null, true);
276
            } catch (MutexException e) {
277
                throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N
278
            }
279
        }
247
280
248
        Thread t = Thread.currentThread();
281
        Thread t = Thread.currentThread();
249
        readEnter(t);
282
        readEnter(t);
Lines 279-288 Link Here
279
    * @exception RuntimeException if any runtime exception is thrown from the run method
312
    * @exception RuntimeException if any runtime exception is thrown from the run method
280
    * @see #readAccess(Mutex.Action)
313
    * @see #readAccess(Mutex.Action)
281
    */
314
    */
282
    public <T> T readAccess(ExceptionAction<T> action) throws MutexException {
315
    public <T> T readAccess(final ExceptionAction<T> action) throws MutexException {
283
        if (this == EVENT) {
316
        if (this == EVENT) {
284
            return doEventAccess(action);
317
            return doEventAccess(action);
285
        }
318
        }
319
        if (wrapper != null) {
320
            return doWrapperAccess(action, null, true);
321
        }
286
322
287
        Thread t = Thread.currentThread();
323
        Thread t = Thread.currentThread();
288
        readEnter(t);
324
        readEnter(t);
Lines 310-315 Link Here
310
346
311
            return;
347
            return;
312
        }
348
        }
349
        if (wrapper != null) {
350
            try {
351
                doWrapperAccess(null, action, true);
352
                return;
353
            } catch (MutexException ex) {
354
                throw (IllegalStateException)new IllegalStateException().initCause(ex);
355
            }
356
        }
313
357
314
        Thread t = Thread.currentThread();
358
        Thread t = Thread.currentThread();
315
        readEnter(t);
359
        readEnter(t);
Lines 335-340 Link Here
335
                throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N
379
                throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N
336
            }
380
            }
337
        }
381
        }
382
        if (wrapper != null) {
383
            try {
384
                return doWrapperAccess(action, null, false);
385
            } catch (MutexException e) {
386
                throw (InternalError) new InternalError("Exception from non-Exception Action").initCause(e.getException()); // NOI18N
387
            }
388
        }
338
389
339
        Thread t = Thread.currentThread();
390
        Thread t = Thread.currentThread();
340
        writeEnter(t);
391
        writeEnter(t);
Lines 371-376 Link Here
371
        if (this == EVENT) {
422
        if (this == EVENT) {
372
            return doEventAccess(action);
423
            return doEventAccess(action);
373
        }
424
        }
425
        if (wrapper != null) {
426
            return doWrapperAccess(action, null, false);
427
        }
374
428
375
        Thread t = Thread.currentThread();
429
        Thread t = Thread.currentThread();
376
        writeEnter(t);
430
        writeEnter(t);
Lines 399-404 Link Here
399
453
400
            return;
454
            return;
401
        }
455
        }
456
        if (wrapper != null) {
457
            try {
458
                doWrapperAccess(null, action, false);
459
            } catch (MutexException ex) {
460
                throw (IllegalStateException)new IllegalStateException().initCause(ex);
461
            }
462
            return;
463
        }
402
464
403
        Thread t = Thread.currentThread();
465
        Thread t = Thread.currentThread();
404
        writeEnter(t);
466
        writeEnter(t);
Lines 431-436 Link Here
431
        if (this == EVENT) {
493
        if (this == EVENT) {
432
            return javax.swing.SwingUtilities.isEventDispatchThread();
494
            return javax.swing.SwingUtilities.isEventDispatchThread();
433
        }
495
        }
496
        if (wrapper != null) {
497
            Mutex m = (Mutex)LOCK;
498
            return m.isReadAccess();
499
        }
434
500
435
        Thread t = Thread.currentThread();
501
        Thread t = Thread.currentThread();
436
        ThreadInfo info;
502
        ThreadInfo info;
Lines 460-465 Link Here
460
        if (this == EVENT) {
526
        if (this == EVENT) {
461
            return javax.swing.SwingUtilities.isEventDispatchThread();
527
            return javax.swing.SwingUtilities.isEventDispatchThread();
462
        }
528
        }
529
        if (wrapper != null) {
530
            Mutex m = (Mutex)LOCK;
531
            return m.isWriteAccess();
532
        }
463
533
464
        Thread t = Thread.currentThread();
534
        Thread t = Thread.currentThread();
465
        ThreadInfo info;
535
        ThreadInfo info;
Lines 492-498 Link Here
492
     * @param run runnable to run
562
     * @param run runnable to run
493
     */
563
     */
494
    public void postReadRequest(final Runnable run) {
564
    public void postReadRequest(final Runnable run) {
495
        postRequest(S, run);
565
        postRequest(S, run, null);
496
    }
566
    }
497
567
498
    /** Posts a write request. This request runs immediately iff
568
    /** Posts a write request. This request runs immediately iff
Lines 509-515 Link Here
509
     * @param run runnable to run
579
     * @param run runnable to run
510
     */
580
     */
511
    public void postWriteRequest(Runnable run) {
581
    public void postWriteRequest(Runnable run) {
512
        postRequest(X, run);
582
        postRequest(X, run, null);
513
    }
583
    }
514
584
515
    /** toString */
585
    /** toString */
Lines 1128-1141 Link Here
1128
    * @param mutexMode mutex mode for which the action is rquested
1198
    * @param mutexMode mutex mode for which the action is rquested
1129
    * @param run the action
1199
    * @param run the action
1130
    */
1200
    */
1131
    private void postRequest(int mutexMode, Runnable run) {
1201
    private void postRequest(final int mutexMode, final Runnable run, Executor exec) {
1132
        if (this == EVENT) {
1202
        if (this == EVENT) {
1133
            doEventRequest(run);
1203
            doEventRequest(run);
1134
1204
1135
            return;
1205
            return;
1136
        }
1206
        }
1207
        if (wrapper != null) {
1208
            Mutex m = (Mutex)LOCK;
1209
            m.postRequest(mutexMode, run, wrapper);
1210
            return;
1211
        }
1137
1212
1138
        Thread t = Thread.currentThread();
1213
        final Thread t = Thread.currentThread();
1139
        ThreadInfo info;
1214
        ThreadInfo info;
1140
1215
1141
        synchronized (LOCK) {
1216
        synchronized (LOCK) {
Lines 1156-1163 Link Here
1156
1231
1157
        // this mutex is not held
1232
        // this mutex is not held
1158
        if (info == null) {
1233
        if (info == null) {
1234
            if (exec != null) {
1235
                class Exec implements Runnable {
1236
                    public void run() {
1237
                        enter(mutexMode, t, true);
1238
                        try {
1239
                            run.run();
1240
                        } finally {
1241
                            leave(t);
1242
                        }
1243
                    }
1244
                }
1245
                exec.execute(new Exec());
1246
                return;
1247
            }
1248
            
1159
            enter(mutexMode, t, true);
1249
            enter(mutexMode, t, true);
1160
1161
            try {
1250
            try {
1162
                run.run();
1251
                run.run();
1163
            } finally {
1252
            } finally {
Lines 1192-1197 Link Here
1192
    private boolean canUpgrade(int threadGranted, int requested) {
1281
    private boolean canUpgrade(int threadGranted, int requested) {
1193
        return (threadGranted == S) && (requested == X) && (readersNo == 1);
1282
        return (threadGranted == S) && (requested == X) && (readersNo == 1);
1194
    }
1283
    }
1284
    
1285
    // -------------------------------- WRAPPERS --------------------------------
1286
    
1287
    private <T> T doWrapperAccess(
1288
        final ExceptionAction<T> action, final Runnable runnable, final boolean readOnly
1289
    ) throws MutexException {
1290
        class R implements Runnable {
1291
            T ret;
1292
            MutexException e;
1293
            
1294
            public void run() {
1295
                Mutex m = (Mutex)LOCK;
1296
                try {
1297
                    if (readOnly) {
1298
                        if (action != null) {
1299
                            ret = m.readAccess(action);
1300
                        } else {
1301
                            m.readAccess(runnable);
1302
                        }
1303
                    } else {
1304
                        if (action != null) {
1305
                            ret = m.writeAccess(action);
1306
                        } else {
1307
                            m.writeAccess(runnable);
1308
                        }
1309
                    }
1310
                } catch (MutexException ex) {
1311
                    this.e = ex;
1312
                }
1313
            }
1314
        }
1315
        R run = new R();
1316
        wrapper.execute(run);
1317
        if (run.e != null) {
1318
            throw run.e;
1319
        }
1320
        return run.ret;
1321
    }
1195
1322
1196
    // ------------------------------- EVENT METHODS ----------------------------
1323
    // ------------------------------- EVENT METHODS ----------------------------
1197
1324
Lines 1484-1490 Link Here
1484
            notifyAll();
1611
            notifyAll();
1485
        }
1612
        }
1486
    }
1613
    }
1487
1614
    
1488
    /** Provides access to Mutex's internal methods.
1615
    /** Provides access to Mutex's internal methods.
1489
     *
1616
     *
1490
     * This class can be used when one wants to avoid creating a
1617
     * This class can be used when one wants to avoid creating a
(-)test/unit/src/org/openide/util/MutexWrapTest.java (+195 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
package org.openide.util;
43
44
import java.util.concurrent.Executor;
45
import junit.framework.Test;
46
import org.netbeans.junit.NbTestCase;
47
import org.netbeans.junit.NbTestSuite;
48
import org.openide.util.Mutex.Action;
49
import org.openide.util.Mutex.ExceptionAction;
50
51
52
public class MutexWrapTest extends NbTestCase implements Executor {
53
    Mutex.Privileged p;
54
    Mutex m;
55
    ThreadLocal<Object> IN = new ThreadLocal<Object>();
56
57
    public MutexWrapTest(java.lang.String testName) {
58
        super(testName);
59
    }
60
61
    public static Test suite() {
62
//        return new MutexWrapTest("testPostRead");
63
        return new NbTestSuite(MutexWrapTest.class);
64
    }
65
    
66
    /** Sets up the test.
67
     */
68
    @Override
69
    protected void setUp () {
70
        p = new Mutex.Privileged ();
71
        m = new Mutex (p, this);
72
    }
73
    
74
    public void testRead() throws Exception {
75
        A arg = new A();
76
        Object ret = m.readAccess(arg);
77
        assertEquals("Return type is ok", arg, ret);
78
    }
79
    public void testWrite() throws Exception {
80
        A arg = new A();
81
        Object ret = m.writeAccess(arg);
82
        assertEquals("Return type is ok", arg, ret);
83
    }
84
    public void testExRead() throws Exception {
85
        E arg = new E();
86
        Object ret = m.readAccess(arg);
87
        assertEquals("Return type is ok", arg, ret);
88
    }
89
    public void testExWrite() throws Exception {
90
        E arg = new E();
91
        Object ret = m.writeAccess(arg);
92
        assertEquals("Return type is ok", arg, ret);
93
    }
94
    public void testRunRead() throws Exception {
95
        R arg = new R();
96
        m.readAccess(arg);
97
        assertTrue("Executed", arg.exec);
98
    }
99
    public void testRunWrite() throws Exception {
100
        R arg = new R();
101
        m.writeAccess(arg);
102
        assertTrue("Executed", arg.exec);
103
    }
104
    public void testPostRead() throws Exception {
105
        R arg = new R();
106
        m.postReadRequest(arg);
107
        assertTrue("Executed", arg.exec);
108
    }
109
    public void testPostReadFromWrite() throws Exception {
110
        R arg = new R();
111
        Del del = new Del();
112
        del.read = arg;
113
        m.writeAccess(del);
114
        assertTrue("Executed", arg.exec);
115
    }
116
    public void testPostReadFromRead() throws Exception {
117
        R arg = new R();
118
        Del del = new Del();
119
        del.read = arg;
120
        m.readAccess(del);
121
        assertTrue("Executed", arg.exec);
122
    }
123
    public void testPostWrite() throws Exception {
124
        R arg = new R();
125
        m.postWriteRequest(arg);
126
        assertTrue("Executed", arg.exec);
127
    }
128
    public void testPostWriteFromRead() throws Exception {
129
        R arg = new R();
130
        Del del = new Del();
131
        del.write = arg;
132
        m.readAccess(del);
133
        assertTrue("Executed", arg.exec);
134
    }
135
    public void testPostWriteFromWrite() throws Exception {
136
        R arg = new R();
137
        Del del = new Del();
138
        del.write = arg;
139
        m.writeAccess(del);
140
        assertTrue("Executed", arg.exec);
141
    }
142
    
143
    
144
    private class A implements Mutex.Action<Object> {
145
        boolean exec;
146
        
147
        public Object run() {
148
            exec = true;
149
            assertEquals("I am wrapped", MutexWrapTest.this, IN.get());
150
            return this;
151
        }
152
    }
153
    private class E implements Mutex.ExceptionAction<Object> {
154
        boolean exec;
155
        
156
        public Object run() {
157
            exec = true;
158
            assertEquals("I am wrapped", MutexWrapTest.this, IN.get());
159
            return this;
160
        }
161
    }
162
    private class R implements Runnable {
163
        boolean exec;
164
        
165
        public void run() {
166
            exec = true;
167
            assertEquals("I am wrapped", MutexWrapTest.this, IN.get());
168
        }
169
    }
170
    private class Del implements Runnable {
171
        Runnable write;
172
        Runnable read;
173
        
174
        public void run() {
175
            if (write != null) {
176
                m.postWriteRequest(write);
177
            }
178
            if (read != null) {
179
                m.postReadRequest(read);
180
            }
181
        }
182
    }
183
    public void execute(final Runnable run) {
184
        Object prev = IN.get();
185
        IN.set(MutexWrapTest.this);
186
        try {
187
            run.run();
188
        } finally {
189
            IN.set(prev);
190
        }
191
        assertFalse("No read", m.isReadAccess());
192
        assertFalse("No write", m.isWriteAccess());
193
    }
194
195
}

Return to bug 123832