# HG changeset patch # User Jaroslav Tulach # Date 1213430076 -7200 # Node ID 3905a2e66b9b68f6a54aa33538275118934a51ea # Parent 0d81e12595626c66ed5f0b884f70af8ec49cb966 Sample code with various attempts to fight with reentrant code diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/build.xml Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,69 @@ + + + + + + Builds, tests, and runs the project reentrant. + + + diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/nbproject/build-impl.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/nbproject/build-impl.xml Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,627 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/nbproject/genfiles.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/nbproject/genfiles.properties Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=bd3226d8 +build.xml.script.CRC32=b09f34e1 +build.xml.stylesheet.CRC32=be360661 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=bd3226d8 +nbproject/build-impl.xml.script.CRC32=3aa23054 +nbproject/build-impl.xml.stylesheet.CRC32=f1d9da08 diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/nbproject/project.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/nbproject/project.properties Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,59 @@ +application.title=reentrant +application.vendor=jarda +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/reentrant.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +file.reference.junit-4.4.jar=../libs/dist/junit-4.4.jar +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.5 +javac.target=1.5 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${file.reference.junit-4.4.jar} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs=-ea +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/nbproject/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/nbproject/project.xml Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,16 @@ + + + org.netbeans.modules.java.j2seproject + + + reentrant + 1.6.5 + + + + + + + + + diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/src/org/apidesign/reentrant/CriticalSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSection.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,10 @@ +package org.apidesign.reentrant; + +import java.util.Collection; + +public interface CriticalSection> { + + public void assignPilot(T pilot); + public int sumBigger(Collection args); + public int getCount(); +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/src/org/apidesign/reentrant/CriticalSectionReentrant.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionReentrant.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,31 @@ +package org.apidesign.reentrant; + +import java.util.Collection; +import java.util.concurrent.atomic.AtomicInteger; + +public class CriticalSectionReentrant> implements CriticalSection { + private T pilot; + private AtomicInteger cnt = new AtomicInteger(); + + public void assignPilot(T pilot) { + this.pilot = pilot; + } + + public int sumBigger(Collection args) { + T pilotCopy = this.pilot; + int own = 0; + for (T cmp : args) { + if (pilotCopy.compareTo(cmp) < 0) { + own++; + } + } + cnt.addAndGet(own); + return own; + + + } + + public int getCount() { + return cnt.get(); + } +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronized.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronized.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,25 @@ +package org.apidesign.reentrant; + +import java.util.Collection; + +public class CriticalSectionSynchronized> implements CriticalSection { + private T pilot; + private int cnt; + + public synchronized void assignPilot(T pilot) { + this.pilot = pilot; + } + + public int sumBigger(Collection args) { + for (T cmp : args) { + if (pilot.compareTo(cmp) < 0) { + cnt++; + } + } + return cnt; + } + + public int getCount() { + return cnt; + } +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithAssert.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithAssert.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,34 @@ +package org.apidesign.reentrant; + +import java.util.Collection; + +public class CriticalSectionSynchronizedWithAssert> implements CriticalSection { + private T pilot; + private int cnt; + private boolean working; + + public synchronized void assignPilot(T pilot) { + assert !working : "Shall not be working yet in order to be consistent"; + this.pilot = pilot; + } + + public int sumBigger(Collection args) { + assert !working : "Shall not be working yet in order to be consistent"; + working = true; + try { + for (T cmp : args) { + if (pilot.compareTo(cmp) < 0) { + cnt++; + } + } + return cnt; + } finally { + working = false; + } + } + + public int getCount() { + assert !working : "Shall not be working yet in order to be consistent"; + return cnt; + } +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithNonReentrantLock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithNonReentrantLock.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,43 @@ +package org.apidesign.reentrant; + +import java.nio.channels.NonReadableChannelException; +import java.util.Collection; +import java.util.concurrent.locks.Lock; + +public class CriticalSectionSynchronizedWithNonReentrantLock> implements CriticalSection { + private T pilot; + private int cnt; + private Lock lock = new NonReentrantLock(); + + public void assignPilot(T pilot) { + lock.lock(); + try { + this.pilot = pilot; + } finally { + lock.unlock(); + } + } + + public int sumBigger(Collection args) { + lock.lock(); + try { + for (T cmp : args) { + if (pilot.compareTo(cmp) < 0) { + cnt++; + } + } + return cnt; + } finally { + lock.unlock(); + } + } + + public int getCount() { + lock.lock(); + try { + return cnt; + } finally { + lock.unlock(); + } + } +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/src/org/apidesign/reentrant/NonReentrantLock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/src/org/apidesign/reentrant/NonReentrantLock.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,22 @@ +package org.apidesign.reentrant; + +import java.util.concurrent.locks.ReentrantLock; + +final class NonReentrantLock extends ReentrantLock { + @Override + public void lock() { + if (isHeldByCurrentThread()) { + throw new IllegalStateException("Attempt to reentrant lock"); + } + super.lock(); + } + + @Override + public void lockInterruptibly() throws InterruptedException { + if (isHeldByCurrentThread()) { + throw new IllegalStateException("Attempt to reentrant lock"); + } + super.lockInterruptibly(); + } + +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/test/org/apidesign/reentrant/CriticalSectionBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionBase.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,101 @@ +package org.apidesign.reentrant; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.junit.Test; +import static org.junit.Assert.*; + +public abstract class CriticalSectionBase { + protected abstract CriticalSection create(); + + @Test + public void testCriticalSectionWith15() { + final CriticalSection cs = create(); + testFor15(cs); + } + + final void testFor15(CriticalSection cs) { + cs.assignPilot(15); + + List ints = new ArrayList(); + ints.add(8); + ints.add(11); + ints.add(10); + ints.add(5); + ints.add(12); + ints.add(18); + ints.add(13); + ints.add(7); + + int cnt = cs.sumBigger(ints); + + assertEquals("18 is bigger than 15", 1, cnt); + + } + + @Test + public void teaseCriticalSectionWithReentrantCalls() { + final CriticalSection cs = create(); + + cs.assignPilot(10); + + class ChangePilotTo15 implements Runnable { + public void run() { + testFor15(cs); + } + } + + List ints = new MyCollection(new ChangePilotTo15(), 3); + ints.add(8); + ints.add(11); + ints.add(10); + ints.add(5); + ints.add(12); + ints.add(18); + ints.add(13); + ints.add(7); + + int cnt = cs.sumBigger(ints); + + assertEquals("11, 12, 18, 13 are bigger than 10", 4, cnt); + + assertEquals("Global count is sum of ints(e.g. 4) plus result of testFor15(e.g. 1)", 5, cs.getCount()); + } + + class MyCollection extends ArrayList { + private final Runnable callback; + private final int callbackBeforeIndex; + + public MyCollection(Runnable callback, int callbackAtIndex) { + this.callback = callback; + this.callbackBeforeIndex = callbackAtIndex; + } + + @Override + public Iterator iterator() { + final Iterator delegate = super.iterator(); + class It implements Iterator { + private int index; + + public boolean hasNext() { + return delegate.hasNext(); + } + + public Integer next() { + if (index++ == callbackBeforeIndex) { + callback.run(); + } + + return delegate.next(); + } + + public void remove() { + delegate.remove(); + } + } // end of It + + return new It(); + } + } +} \ No newline at end of file diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/test/org/apidesign/reentrant/CriticalSectionReentrantTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionReentrantTest.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,8 @@ +package org.apidesign.reentrant; + +public class CriticalSectionReentrantTest extends CriticalSectionBase { + @Override + protected CriticalSection create() { + return new CriticalSectionReentrant(); + } +} diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/test/org/apidesign/reentrant/CriticalSectionSynchronizedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionSynchronizedTest.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,8 @@ +package org.apidesign.reentrant; + +public class CriticalSectionSynchronizedTest extends CriticalSectionBase { + @Override + protected CriticalSection create() { + return new CriticalSectionSynchronized(); + } +} \ No newline at end of file diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/test/org/apidesign/reentrant/CriticalSectionSynchronizedWithAssertTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionSynchronizedWithAssertTest.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,9 @@ +package org.apidesign.reentrant; + +public class CriticalSectionSynchronizedWithAssertTest extends CriticalSectionBase { + @Override + protected CriticalSection create() { + return new CriticalSectionSynchronizedWithAssert(); + } + +} \ No newline at end of file diff -r 0d81e1259562 -r 3905a2e66b9b samples/reentrant/test/org/apidesign/reentrant/CriticalSectionSynchronizedWithNonReentrantLockTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionSynchronizedWithNonReentrantLockTest.java Sat Jun 14 09:54:36 2008 +0200 @@ -0,0 +1,10 @@ +package org.apidesign.reentrant; + +public class CriticalSectionSynchronizedWithNonReentrantLockTest extends CriticalSectionBase { + + @Override + protected CriticalSection create() { + return new CriticalSectionSynchronizedWithNonReentrantLock(); + } + +} \ No newline at end of file