/** * Copyright 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ package com.jogamp.common.util.locks; import com.jogamp.common.util.locks.RecursiveLock; import java.lang.reflect.*; import java.io.IOException; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.After; import org.junit.AfterClass; import org.junit.Test; public class TestRecursiveLock01 { static final int YIELD_NONE = 0; static final int YIELD_YIELD = 1; static final int YIELD_SLEEP = 2; static void yield(int mode) { switch(mode) { case YIELD_YIELD: Thread.yield(); break; case YIELD_SLEEP: try { Thread.sleep(20); } catch (InterruptedException ie) { ie.printStackTrace(); } break; default: break; } } static class LockedObject { static final boolean DEBUG = false; public LockedObject() { locker = new RecursiveLock(); actionCounter = 0; } public final void action1Direct(int l, int yieldMode) { if(DEBUG) { System.err.print("<a1"); } lock(); try { if(DEBUG) { System.err.print("+"); } while(l>0) l--; actionCounter++; yield(yieldMode); } finally { if(DEBUG) { System.err.print("-"); } unlock(); if(DEBUG) { System.err.println(">"); } } } class Action2 implements Runnable { int l, yieldMode; Action2(int l, int yieldMode) { this.l=l; this.yieldMode=yieldMode; } public void run() { if(DEBUG) { System.err.print("[a2"); } lock(); try { if(DEBUG) { System.err.print("+"); } while(l>0) l--; actionCounter++; yield(yieldMode); } finally { if(DEBUG) { System.err.print("-"); } unlock(); if(DEBUG) { System.err.println("]"); } } } } public final void action2Deferred(int l, int yieldMode) { Thread thread = new Thread(new Action2(l, yieldMode), Thread.currentThread()+"-action2Deferred"); thread.start(); } public final void lock() { locker.lock(); } public final void unlock() { locker.unlock(); } public final boolean isLocked() { return locker.isLocked(); } RecursiveLock locker; int actionCounter; } interface LockedObjectIf extends Runnable { void stop(); boolean isStopped(); int remaining(); } class LockedObjectAction1 implements LockedObjectIf { boolean shouldStop; boolean stopped; LockedObject lo; volatile int loops; int iloops; int yieldMode; public LockedObjectAction1(LockedObject lo, int loops, int iloops, int yieldMode) { this.lo = lo; this.loops = loops; this.iloops = iloops; this.shouldStop = false; this.stopped = false; this.yieldMode = yieldMode; } public final synchronized void stop() { shouldStop = true; } public final synchronized boolean isStopped() { return stopped; } public final int remaining() { return loops; } public void run() { while(!shouldStop && loops>0) { lo.action1Direct(iloops, yieldMode); lo.action2Deferred(iloops, yieldMode); loops--; } synchronized(this) { stopped = true; notifyAll(); } } } protected void testLockedObjectImpl(int threadNum, int loops, int iloops, int yieldMode) throws InterruptedException { LockedObject lo = new LockedObject(); LockedObjectIf[] runners = new LockedObjectIf[threadNum]; Thread[] threads = new Thread[threadNum]; int i; for(i=0; i<threadNum; i++) { runners[i] = new LockedObjectAction1(lo, loops, iloops, yieldMode); threads[i] = new Thread( runners[i], Thread.currentThread()+"-ActionThread-"+i+"/"+threadNum); threads[i].start(); } int active; do { active = threadNum; for(i=0; i<threadNum; i++) { if(runners[i].isStopped()) { active--; } } yield(yieldMode); } while(0<active); } // @Test public void testLockedObjectThreading2x10000() throws InterruptedException { System.err.println("++++ TestRecursiveLock01.testLockedObjectThreading2x10000"); testLockedObjectImpl(2, 10000, 10000, YIELD_NONE); System.err.println("---- TestRecursiveLock01.testLockedObjectThreading2x10000"); } @Test public void testLockedObjectThreading200x200Yield() throws InterruptedException { System.err.println("++++ TestRecursiveLock01.testLockedObjectThreading200x200-Yield"); testLockedObjectImpl(200, 200, 100, YIELD_YIELD); System.err.println("---- TestRecursiveLock01.testLockedObjectThreading200x200-Yield"); } // @Test public void testLockedObjectThreading200x200Sleep() throws InterruptedException { System.err.println("++++ TestRecursiveLock01.testLockedObjectThreading200x200-Sleep"); testLockedObjectImpl(200, 200, 100, YIELD_SLEEP); System.err.println("---- TestRecursiveLock01.testLockedObjectThreading200x200-Sleep"); } @Test public void testLockedObjectThreading200x200None() throws InterruptedException { System.err.println("++++ TestRecursiveLock01.testLockedObjectThreading200x200-None"); testLockedObjectImpl(200, 200, 100, YIELD_NONE); System.err.println("---- TestRecursiveLock01.testLockedObjectThreading200x200-None"); } static int atoi(String a) { int i=0; try { i = Integer.parseInt(a); } catch (Exception ex) { ex.printStackTrace(); } return i; } public static void main(String args[]) throws IOException { String tstname = TestRecursiveLock01.class.getName(); org.junit.runner.JUnitCore.main(tstname); } }