GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
TestRecursiveThreadGroupLock01.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;
32
33import org.junit.Assert;
34import org.junit.Test;
35
36import com.jogamp.common.os.Platform;
37import com.jogamp.common.util.InterruptSource;
38import com.jogamp.junit.util.SingletonJunitCase;
39
40import org.junit.FixMethodOrder;
41import org.junit.runners.MethodSorters;
42
43@FixMethodOrder(MethodSorters.NAME_ASCENDING)
45
46 public enum YieldMode {
47 NONE(0), YIELD(1), SLEEP(2);
48
49 public final int id;
50
51 YieldMode(final int id){
52 this.id = id;
53 }
54 }
55
56 static void yield_thread(final YieldMode mode) {
57 switch(mode) {
58 case YIELD:
59 Thread.yield();
60 break;
61 case SLEEP:
62 try {
63 Thread.sleep(10);
64 } catch (final InterruptedException ie) {
65 ie.printStackTrace();
66 }
67 break;
68 default:
69 break;
70 }
71
72 }
73
74 static class LockedObject {
75 static final boolean DEBUG = false;
76
77 private final RecursiveThreadGroupLock locker; // post
78 private volatile int slaveCounter;
79
80 public LockedObject() {
81 locker = LockFactory.createRecursiveThreadGroupLock();
82 slaveCounter = 0;
83 }
84
85 public final void masterAction(final String tab, final String name, final Thread[] slaves, final int loops, final int mark, final YieldMode yieldMode) {
86 locker.lock();
87 if(DEBUG) {
88 System.err.println(tab+"<"+name+" c "+slaveCounter);
89 }
90 Assert.assertTrue(mark>loops);
91 Assert.assertTrue(loops*loops>mark);
92 try {
93 if(slaveCounter<mark) {
94 for(int i=0; i<slaves.length; i++) {
95 locker.addOwner(slaves[i]);
96 slaves[i].start();
97 }
98 while(slaveCounter<mark) {
99 yield_thread(yieldMode);
100 }
101 }
102 } finally {
103 if(DEBUG) {
104 System.err.println(tab+" "+name+" c "+slaveCounter+">");
105 }
106 // Implicit waits until all slaves got off the lock
107 locker.unlock();
108 }
109 }
110
111 public final void slaveAction(final String tab, final String name, int loops, final int mark, final YieldMode yieldMode) {
112 if(slaveCounter>=mark) {
113 if(DEBUG) {
114 System.err.println(tab+"["+name+" c "+slaveCounter+" - NOP]");
115 }
116 return;
117 }
118 locker.lock();
119 if(DEBUG) {
120 System.err.println(tab+"["+name+" c "+slaveCounter);
121 }
122 Assert.assertTrue(mark>loops);
123 Assert.assertTrue(loops*loops>mark);
124 try {
125 while(loops>0 && slaveCounter<mark) {
126 slaveCounter++;
127 loops--;
128 }
129 /**
130 while(slaveCounter<mark) {
131 slaveCounter++;
132 } */
133 yield_thread(yieldMode);
134 } finally {
135 if(DEBUG) {
136 System.err.println(tab+" "+name+" c "+slaveCounter+"]");
137 }
138 locker.unlock();
139 }
140 }
141
142 public final boolean isLocked() {
143 return locker.isLocked();
144 }
145
146 }
147
148 interface LockedObjectRunner extends Runnable {
149 void stop();
150 boolean isStarted();
151 boolean isStopped();
152 void waitUntilStopped();
153 }
154
155 class LockedObjectRunner1 implements LockedObjectRunner {
156 volatile boolean shouldStop;
157 volatile boolean stopped;
158 volatile boolean started;
159 String tab, name;
160 LockedObject lo;
161 Thread[] slaves;
162 int loops;
163 int mark;
164 YieldMode yieldMode;
165
166 /** master constructor */
167 public LockedObjectRunner1(final String tab, final String name, final LockedObject lo, final Thread[] slaves, final int loops, final int mark, final YieldMode yieldMode) {
168 this.tab = tab;
169 this.name = name;
170 this.lo = lo;
171 this.slaves = slaves;
172 this.loops = loops;
173 this.mark = mark;
174 this.shouldStop = false;
175 this.stopped = false;
176 this.yieldMode = yieldMode;
177 Assert.assertTrue(mark>loops);
178 Assert.assertTrue(loops*loops>mark);
179 }
180
181 /** slave constructor */
182 public LockedObjectRunner1(final String tab, final String name, final LockedObject lo, final int loops, final int mark, final YieldMode yieldMode) {
183 this.tab = tab;
184 this.name = name;
185 this.lo = lo;
186 this.slaves = null; // slave
187 this.loops = loops;
188 this.mark = mark;
189 this.shouldStop = false;
190 this.stopped = false;
191 this.yieldMode = yieldMode;
192 Assert.assertTrue(mark>loops);
193 Assert.assertTrue(loops*loops>mark);
194 }
195
196 public final void stop() {
197 shouldStop = true;
198 }
199
200 public final boolean isStarted() {
201 return started;
202 }
203 public final boolean isStopped() {
204 return stopped;
205 }
206
207 public void waitUntilStopped() {
208 synchronized(this) {
209 while(!stopped) {
210 try {
211 this.wait();
212 } catch (final InterruptedException e) {
213 e.printStackTrace();
214 }
215 }
216 }
217
218 }
219
220 public void run() {
221 synchronized(this) {
222 started = true;
223 for(int i=0; !shouldStop && i<loops; i++) {
224 if(null != slaves) {
225 lo.masterAction(tab, name, slaves, loops, mark, yieldMode);
226 } else {
227 lo.slaveAction(tab, name, loops, mark, yieldMode);
228 }
229 }
230 stopped = true;
231 this.notifyAll();
232 }
233 }
234 }
235
236 protected long testLockedObjectImpl(final LockFactory.ImplType implType, final boolean fair,
237 final int slaveThreadNum, final int concurrentThreadNum,
238 final int loops, final int mark, final YieldMode yieldMode) throws InterruptedException {
239 final long t0 = System.currentTimeMillis();
240 final LockedObject lo = new LockedObject();
241 final LockedObjectRunner[] concurrentRunners = new LockedObjectRunner[concurrentThreadNum];
242 final LockedObjectRunner[] slaveRunners = new LockedObjectRunner[slaveThreadNum];
243 final InterruptSource.Thread[] concurrentThreads = new InterruptSource.Thread[concurrentThreadNum];
244 final InterruptSource.Thread[] slaveThreads = new InterruptSource.Thread[slaveThreadNum];
245 final InterruptSource.Thread[] noCoOwnerThreads = new InterruptSource.Thread[0];
246 int i;
247
248 for(i=0; i<slaveThreadNum; i++) {
249 slaveRunners[i] = new LockedObjectRunner1(" ", "s"+i, lo, loops, mark, yieldMode);
250 final String name = "ActionThread-Slaves-"+i+"_of_"+slaveThreadNum;
251 slaveThreads[i] = new InterruptSource.Thread( null, slaveRunners[i], name );
252 }
253 for(i=0; i<concurrentThreadNum; i++) {
254 String name;
255 if(i==0) {
256 concurrentRunners[i] = new LockedObjectRunner1("", "M0", lo, slaveThreads, loops, mark, yieldMode);
257 name = "ActionThread-Master-"+i+"_of_"+concurrentThreadNum;
258 } else {
259 concurrentRunners[i] = new LockedObjectRunner1(" ", "O"+i, lo, noCoOwnerThreads, loops, mark, yieldMode);
260 name = "ActionThread-Others-"+i+"_of_"+concurrentThreadNum;
261 }
262 concurrentThreads[i] = new InterruptSource.Thread( null, concurrentRunners[i], name );
263 concurrentThreads[i].start();
264 if(i==0) {
265 // master thread w/ slaves shall start first
266 while(!concurrentRunners[i].isStarted()) {
267 Thread.sleep(100);
268 }
269 }
270 }
271
272 for( i=0; i<slaveThreadNum; i++ ) {
273 slaveRunners[i].waitUntilStopped();
274 }
275 for( i=0; i<concurrentThreadNum; i++ ) {
276 concurrentRunners[i].waitUntilStopped();
277 }
278 Assert.assertEquals(0, lo.locker.getHoldCount());
279 Assert.assertEquals(false, lo.locker.isLocked());
280
281 final long dt = System.currentTimeMillis()-t0;
282
283 System.err.println();
284 final String fair_S = fair ? "fair " : "unfair" ;
285 System.err.printf("---- TestRecursiveLock01.testLockedObjectThreading: i %5s, %s, threads %2d, loops-outter %6d, loops-inner %6d, yield %5s - dt %6d ms",
286 implType, fair_S, concurrentThreadNum, loops, mark, yieldMode, dt);
287 System.err.println();
288 return dt;
289 }
290
291 @Test
292 public void testTwoThreadsInGroup() throws InterruptedException {
293 final LockFactory.ImplType t = LockFactory.ImplType.Int02ThreadGroup;
294 final boolean fair=true;
295 final int coOwnerThreadNum=2;
296 final int threadNum=5;
297 int loops=1000;
298 int mark=10000;
299 final YieldMode yieldMode=YieldMode.YIELD;
300
302 loops=5; mark=10;
303 }
304
305 testLockedObjectImpl(t, fair, coOwnerThreadNum, threadNum, loops, mark, yieldMode);
306 }
307
308 public static void main(final String args[]) throws IOException, InterruptedException {
309 final String tstname = TestRecursiveThreadGroupLock01.class.getName();
310 org.junit.runner.JUnitCore.main(tstname);
311
312 /**
313 BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
314 System.err.println("Press enter to continue");
315 System.err.println(stdin.readLine());
316 TestRecursiveLock01 t = new TestRecursiveLock01();
317 t.testLockedObjectThreading5x1000x10000N_Int01_Unfair();
318
319 t.testLockedObjectThreading5x1000x10000N_Int01_Fair();
320 t.testLockedObjectThreading5x1000x10000N_Java5_Fair();
321 t.testLockedObjectThreading5x1000x10000N_Int01_Unfair();
322 t.testLockedObjectThreading5x1000x10000N_Java5_Unfair();
323 */
324 }
325
326}
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 slaveThreadNum, final int concurrentThreadNum, final int loops, final int mark, final YieldMode yieldMode)
Interface exposing java.lang.Thread#interrupt() source, intended for java.lang.Thread specializations...