GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
TestRecursiveLock01.java
Go to the documentation of this file.
1/**
2 * Copyright 2010 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29package com.jogamp.common.util.locks;
30
31import java.io.IOException;
32import java.util.Collections;
33import java.util.HashMap;
34import java.util.Iterator;
35import java.util.Map;
36
37import org.junit.Assert;
38import org.junit.Test;
39
40import com.jogamp.common.os.Clock;
41import com.jogamp.common.os.Platform;
42import com.jogamp.common.util.InterruptSource;
43import com.jogamp.junit.util.SingletonJunitCase;
44
45import org.junit.FixMethodOrder;
46import org.junit.runners.MethodSorters;
47
48@FixMethodOrder(MethodSorters.NAME_ASCENDING)
50
51 public enum YieldMode {
52 NONE(0), YIELD(1), SLEEP(2);
53
54 public final int id;
55
56 YieldMode(final int id){
57 this.id = id;
58 }
59 }
60
61 static void yield_thread(final YieldMode mode) {
62 switch(mode) {
63 case YIELD:
64 Thread.yield();
65 break;
66 case SLEEP:
67 try {
68 Thread.sleep(10);
69 } catch (final InterruptedException ie) {
70 ie.printStackTrace();
71 }
72 break;
73 default:
74 break;
75 }
76
77 }
78
79 static class LockedObject {
80 static final boolean DEBUG = false;
81
82 static class ThreadStat {
83 ThreadStat() {
84 total = 0;
85 counter = 0;
86 }
87 long total; // ns
88 int counter;
89 }
90
91 private final RecursiveLock locker; // post
92 private int deferredThreadCount = 0; // synced
93 private final Map<String, ThreadStat> threadWaitMap = Collections.synchronizedMap(new HashMap<String, ThreadStat>()); // locked
94
95 long avrg; // ns, post
96 long max_deviation; // ns, post
97 long min_deviation; // ns, post
98
99 public LockedObject(final LockFactory.ImplType implType, final boolean fair) {
100 locker = LockFactory.createRecursiveLock(implType, fair);
101 }
102
103 private synchronized void incrDeferredThreadCount() {
104 deferredThreadCount++;
105 }
106 private synchronized void decrDeferredThreadCount() {
107 deferredThreadCount--;
108 }
109 public synchronized int getDeferredThreadCount() {
110 return deferredThreadCount;
111 }
112
113 public final void action1Direct(int l, final YieldMode yieldMode) {
114 if(DEBUG) {
115 System.err.print("<a1");
116 }
117 lock();
118 try {
119 if(DEBUG) {
120 System.err.print("+");
121 }
122 while(l>0) l--;
123 yield_thread(yieldMode);
124 } finally {
125 if(DEBUG) {
126 System.err.print("-");
127 }
128 unlock();
129 if(DEBUG) {
130 System.err.println(">");
131 }
132 }
133 }
134
135 class Action2 implements Runnable {
136 int l;
137 YieldMode yieldMode;
138
139 Action2(final int l, final YieldMode yieldMode) {
140 this.l=l;
141 this.yieldMode=yieldMode;
142 incrDeferredThreadCount();
143 }
144
145 @Override
146 public void run() {
147 if(DEBUG) {
148 System.err.print("[a2");
149 }
150 lock();
151 try {
152 if(DEBUG) {
153 System.err.print("+");
154 }
155 while(l>0) l--;
156 yield_thread(yieldMode);
157 } finally {
158 if(DEBUG) {
159 System.err.print("-");
160 }
161 unlock();
162 if(DEBUG) {
163 System.err.println("]");
164 }
165 }
166 decrDeferredThreadCount();
167 final int dc = getDeferredThreadCount();
168 if(0>dc) {
169 throw new InternalError("deferredThreads: "+dc);
170 }
171 }
172 }
173
174 public final void action2Deferred(final int l, final YieldMode yieldMode) {
175 final Action2 action2 = new Action2(l, yieldMode);
176 new InterruptSource.Thread(null, action2, Thread.currentThread().getName()+"-deferred").start();
177 }
178
179 public final void lock() {
180 long td = Clock.currentNanos();
181 locker.lock();
182 td = Clock.currentNanos() - td;
183
184 final String cur = Thread.currentThread().getName();
185 ThreadStat ts = threadWaitMap.get(cur);
186 if(null == ts) {
187 ts = new ThreadStat();
188 }
189 ts.total += td;
190 ts.counter++;
191 threadWaitMap.put(cur, ts);
192 }
193
194 public final void unlock() {
195 locker.unlock();
196 }
197
198 public final boolean isLocked() {
199 return locker.isLocked();
200 }
201
202 public void stats(final boolean dump) {
203 long timeAllLocks=0;
204 int numAllLocks=0;
205 for(final Iterator<String> i = threadWaitMap.keySet().iterator(); i.hasNext(); ) {
206 final String name = i.next();
207 final ThreadStat ts = threadWaitMap.get(name);
208 timeAllLocks += ts.total;
209 numAllLocks += ts.counter;
210 }
211 max_deviation = Long.MIN_VALUE;
212 min_deviation = Long.MAX_VALUE;
213 avrg = timeAllLocks/numAllLocks;
214 if(dump) {
215 System.err.printf("Average: %6d ms / %6d times = %8d ns",
216 timeAllLocks/1000000, numAllLocks, avrg);
217 System.err.println();
218 }
219 for(final Iterator<String> i = threadWaitMap.keySet().iterator(); i.hasNext(); numAllLocks++) {
220 final String name = i.next();
221 final ThreadStat ts = threadWaitMap.get(name);
222 final long a = ts.total/ts.counter;
223 final long d = a - avrg;
224 max_deviation = Math.max(max_deviation, d);
225 min_deviation = Math.min(min_deviation, d);
226 if(dump) {
227 System.err.printf("%-35s %12d ns / %6d times, a %8d ns, d %8d ns",
228 name, ts.total, ts.counter, a, d);
229 System.err.println();
230 }
231 }
232 if(dump) {
233 System.err.printf("Deviation (min/max): [%8d ns - %8d ns]", min_deviation, max_deviation);
234 System.err.println();
235 }
236 }
237
238 }
239
240 interface LockedObjectRunner extends Runnable {
241 void stop();
242 boolean isStopped();
243 void waitUntilStopped();
244 }
245
246 class LockedObjectRunner1 implements LockedObjectRunner {
247 volatile boolean shouldStop;
248 volatile boolean stopped;
249 LockedObject lo;
250 int loops;
251 int iloops;
252 YieldMode yieldMode;
253
254 public LockedObjectRunner1(final LockedObject lo, final int loops, final int iloops, final YieldMode yieldMode) {
255 this.lo = lo;
256 this.loops = loops;
257 this.iloops = iloops;
258 this.shouldStop = false;
259 this.stopped = false;
260 this.yieldMode = yieldMode;
261 }
262
263 @Override
264 public final void stop() {
265 shouldStop = true;
266 }
267
268 @Override
269 public final boolean isStopped() {
270 return stopped;
271 }
272
273 @Override
274 public void waitUntilStopped() {
275 synchronized(this) {
276 while(!stopped) {
277 try {
278 this.wait();
279 } catch (final InterruptedException e) {
280 e.printStackTrace();
281 }
282 }
283 }
284
285 }
286
287 @Override
288 public void run() {
289 synchronized(this) {
290 while(!shouldStop && loops>0) {
291 lo.action1Direct(iloops, yieldMode);
292 lo.action2Deferred(iloops, yieldMode);
293 loops--;
294 }
295 stopped = true;
296 this.notifyAll();
297 }
298 }
299 }
300
301 protected long testLockedObjectImpl(final LockFactory.ImplType implType, final boolean fair,
302 final int threadNum, final int loops, final int iloops, final YieldMode yieldMode) throws InterruptedException {
303 final long t0 = System.currentTimeMillis();
304 final LockedObject lo = new LockedObject(implType, fair);
305 final LockedObjectRunner[] runners = new LockedObjectRunner[threadNum];
306 final InterruptSource.Thread[] threads = new InterruptSource.Thread[threadNum];
307 int i;
308
309 for(i=0; i<threadNum; i++) {
310 runners[i] = new LockedObjectRunner1(lo, loops, iloops, yieldMode);
311 // String name = Thread.currentThread().getName()+"-ActionThread-"+i+"_of_"+threadNum;
312 final String name = "ActionThread-"+i+"_of_"+threadNum;
313 threads[i] = new InterruptSource.Thread( null, runners[i], name );
314 threads[i].start();
315 }
316
317 for( i=0; i<threadNum; i++ ) {
318 runners[i].waitUntilStopped();
319 }
320 while( 0 < lo.getDeferredThreadCount() ) {
321 Thread.sleep(100);
322 }
323 Assert.assertEquals(0, lo.locker.getHoldCount());
324 Assert.assertEquals(false, lo.locker.isLocked());
325 Assert.assertEquals(0, lo.getDeferredThreadCount());
326
327 final long dt = System.currentTimeMillis()-t0;
328 lo.stats(false);
329
330 System.err.println();
331 final String fair_S = fair ? "fair " : "unfair" ;
332 System.err.printf("---- TestRecursiveLock01.testLockedObjectThreading: i %5s, %s, threads %2d, loops-outter %6d, loops-inner %6d, yield %5s - dt %6d ms, avrg %8d ns, deviation [ %8d .. %8d ] ns",
333 implType, fair_S, threadNum, loops, iloops, yieldMode, dt, lo.avrg, lo.min_deviation, lo.max_deviation);
334 System.err.println();
335 return dt;
336 }
337
338 @Test
339 public void testLockedObjectThreading5x1000x10000N_Int01_Fair() throws InterruptedException {
340 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
341 final boolean fair=true;
342 int threadNum=5;
343 int loops=1000;
344 int iloops=10000;
345 final YieldMode yieldMode=YieldMode.NONE;
346
348 threadNum=5; loops=5; iloops=10;
349 }
350
351 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
352 }
353
354 @Test
355 public void testLockedObjectThreading5x1000x10000N_Java5_Fair() throws InterruptedException {
356 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
357 final boolean fair=true;
358 int threadNum=5;
359 int loops=1000;
360 int iloops=10000;
361 final YieldMode yieldMode=YieldMode.NONE;
362
364 threadNum=5; loops=5; iloops=10;
365 }
366
367 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
368 }
369
370 @Test
371 public void testLockedObjectThreading5x1000x10000N_Int01_Unfair() throws InterruptedException {
372 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
373 final boolean fair=false;
374 int threadNum=5;
375 int loops=1000;
376 int iloops=10000;
377 final YieldMode yieldMode=YieldMode.NONE;
378
380 threadNum=5; loops=5; iloops=10;
381 }
382
383 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
384 }
385
386 @Test
387 public void testLockedObjectThreading5x1000x10000N_Java5_Unfair() throws InterruptedException {
388 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
389 final boolean fair=false;
390 int threadNum=5;
391 int loops=1000;
392 int iloops=10000;
393 final YieldMode yieldMode=YieldMode.NONE;
394
396 threadNum=5; loops=5; iloops=10;
397 }
398
399 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
400 }
401
402 @Test
403 public void testLockedObjectThreading25x100x100Y_Int01_Fair() throws InterruptedException {
404 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
405 final boolean fair=true;
406 int threadNum=25;
407 int loops=100;
408 int iloops=100;
409 final YieldMode yieldMode=YieldMode.YIELD;
410
412 threadNum=5; loops=5; iloops=10;
413 }
414
415 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
416 }
417
418 @Test
419 public void testLockedObjectThreading25x100x100Y_Java5_Fair() throws InterruptedException {
420 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
421 final boolean fair=true;
422 int threadNum=25;
423 int loops=100;
424 int iloops=100;
425 final YieldMode yieldMode=YieldMode.YIELD;
426
428 threadNum=5; loops=5; iloops=10;
429 }
430
431 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
432 }
433
434 @Test
435 public void testLockedObjectThreading25x100x100Y_Int01_Unair() throws InterruptedException {
436 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
437 final boolean fair=false;
438 int threadNum=25;
439 int loops=100;
440 int iloops=100;
441 final YieldMode yieldMode=YieldMode.YIELD;
442
444 threadNum=5; loops=5; iloops=10;
445 }
446
447 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
448 }
449
450 @Test
451 public void testLockedObjectThreading25x100x100Y_Java5_Unfair() throws InterruptedException {
452 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
453 final boolean fair=false;
454 int threadNum=25;
455 int loops=100;
456 int iloops=100;
457 final YieldMode yieldMode=YieldMode.YIELD;
458
460 threadNum=5; loops=5; iloops=10;
461 }
462
463 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
464 }
465
466 // @Test
467 public void testLockedObjectThreading25x100x100S_Int01_Fair() throws InterruptedException {
468 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
469 final boolean fair=true;
470 int threadNum=25;
471 int loops=100;
472 int iloops=100;
473 final YieldMode yieldMode=YieldMode.SLEEP;
474
476 threadNum=5; loops=5; iloops=10;
477 }
478
479 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
480 }
481
482 // @Test
483 public void testLockedObjectThreading25x100x100S_Java5() throws InterruptedException {
484 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
485 final boolean fair=true;
486 int threadNum=25;
487 int loops=100;
488 int iloops=100;
489 final YieldMode yieldMode=YieldMode.SLEEP;
490
492 threadNum=5; loops=5; iloops=10;
493 }
494
495 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
496 }
497
498 @Test
499 public void testLockedObjectThreading25x100x100N_Int01_Fair() throws InterruptedException {
500 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
501 final boolean fair=true;
502 int threadNum=25;
503 int loops=100;
504 int iloops=100;
505 final YieldMode yieldMode=YieldMode.NONE;
506
508 threadNum=5; loops=5; iloops=10;
509 }
510
511 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
512 }
513
514 @Test
515 public void testLockedObjectThreading25x100x100N_Java5_Fair() throws InterruptedException {
516 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
517 final boolean fair=true;
518 int threadNum=25;
519 int loops=100;
520 int iloops=100;
521 final YieldMode yieldMode=YieldMode.NONE;
522
524 threadNum=5; loops=5; iloops=10;
525 }
526
527 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
528 }
529
530 @Test
531 public void testLockedObjectThreading25x100x100N_Int01_Unfair() throws InterruptedException {
532 final LockFactory.ImplType t = LockFactory.ImplType.Int01;
533 final boolean fair=false;
534 int threadNum=25;
535 int loops=100;
536 int iloops=100;
537 final YieldMode yieldMode=YieldMode.NONE;
538
540 threadNum=5; loops=5; iloops=10;
541 }
542
543 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
544 }
545
546 @Test
547 public void testLockedObjectThreading25x100x100N_Java5_Unfair() throws InterruptedException {
548 final LockFactory.ImplType t = LockFactory.ImplType.Java5;
549 final boolean fair=false;
550 int threadNum=25;
551 int loops=100;
552 int iloops=100;
553 final YieldMode yieldMode=YieldMode.NONE;
554
556 threadNum=5; loops=5; iloops=10;
557 }
558
559 testLockedObjectImpl(t, fair, threadNum, loops, iloops, yieldMode);
560 }
561
562 static int atoi(final String a) {
563 int i=0;
564 try {
565 i = Integer.parseInt(a);
566 } catch (final Exception ex) { ex.printStackTrace(); }
567 return i;
568 }
569
570 public static void main(final String args[]) throws IOException, InterruptedException {
571 final String tstname = TestRecursiveLock01.class.getName();
572 org.junit.runner.JUnitCore.main(tstname);
573
574 /**
575 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
576 System.err.println("Press enter to continue");
577 System.err.println(stdin.readLine());
578 TestRecursiveLock01 t = new TestRecursiveLock01();
579 t.testLockedObjectThreading5x1000x10000N_Int01_Unfair();
580
581 t.testLockedObjectThreading5x1000x10000N_Int01_Fair();
582 t.testLockedObjectThreading5x1000x10000N_Java5_Fair();
583 t.testLockedObjectThreading5x1000x10000N_Int01_Unfair();
584 t.testLockedObjectThreading5x1000x10000N_Java5_Unfair();
585 */
586 }
587
588}
Utility class for querying platform specific properties.
Definition: Platform.java:58
static CPUFamily getCPUFamily()
Returns the CPU family.
Definition: Platform.java:408
java.lang.Thread specialization implementing InterruptSource to track java.lang.Thread#interrupt() ca...
long testLockedObjectImpl(final LockFactory.ImplType implType, final boolean fair, final int threadNum, final int loops, final int iloops, final YieldMode yieldMode)
Interface exposing java.lang.Thread#interrupt() source, intended for java.lang.Thread specializations...