1.1 --- a/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionReentrant.java Sat Jun 14 09:54:36 2008 +0200
1.2 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionReentrant.java Sat Jun 14 09:54:37 2008 +0200
1.3 @@ -13,16 +13,20 @@
1.4
1.5 public int sumBigger(Collection<T> args) {
1.6 T pilotCopy = this.pilot;
1.7 + int own = doCriticalSection(args, pilotCopy);
1.8 + // now merge with global state
1.9 + cnt.addAndGet(own);
1.10 + return own;
1.11 + }
1.12 +
1.13 + private int doCriticalSection(Collection<T> args, T pilotCopy) {
1.14 int own = 0;
1.15 for (T cmp : args) {
1.16 if (pilotCopy.compareTo(cmp) < 0) {
1.17 own++;
1.18 }
1.19 }
1.20 - cnt.addAndGet(own);
1.21 return own;
1.22 -
1.23 -
1.24 }
1.25
1.26 public int getCount() {
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionReentrantForLoop.java Sat Jun 14 09:54:37 2008 +0200
2.3 @@ -0,0 +1,42 @@
2.4 +package org.apidesign.reentrant;
2.5 +
2.6 +import java.util.Collection;
2.7 +import java.util.concurrent.atomic.AtomicInteger;
2.8 +
2.9 +public class CriticalSectionReentrantForLoop<T extends Comparable<T>> implements CriticalSection<T> {
2.10 + private volatile T pilot;
2.11 + private AtomicInteger cnt = new AtomicInteger();
2.12 +
2.13 + public void assignPilot(T pilot) {
2.14 + this.pilot = pilot;
2.15 + }
2.16 +
2.17 + // BEGIN: reentrant.merge.for
2.18 + public int sumBigger(Collection<T> args) {
2.19 + T pilotCopy = this.pilot;
2.20 + for (;;) {
2.21 + int previous = cnt.get();
2.22 + int own = doCriticalSection(args, pilotCopy);
2.23 + // if there was no parallel or reentrant change,
2.24 + // apply and return. Otherwise try once more.
2.25 + if (cnt.compareAndSet(previous, own + previous)) {
2.26 + return own;
2.27 + }
2.28 + }
2.29 + }
2.30 + // END: reentrant.merge.for
2.31 +
2.32 + private int doCriticalSection(Collection<T> args, T pilotCopy) {
2.33 + int own = 0;
2.34 + for (T cmp : args) {
2.35 + if (pilotCopy.compareTo(cmp) < 0) {
2.36 + own++;
2.37 + }
2.38 + }
2.39 + return own;
2.40 + }
2.41 +
2.42 + public int getCount() {
2.43 + return cnt.get();
2.44 + }
2.45 +}
3.1 --- a/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithAssert.java Sat Jun 14 09:54:36 2008 +0200
3.2 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithAssert.java Sat Jun 14 09:54:37 2008 +0200
3.3 @@ -5,27 +5,34 @@
3.4 public class CriticalSectionSynchronizedWithAssert<T extends Comparable<T>> implements CriticalSection<T> {
3.5 private T pilot;
3.6 private int cnt;
3.7 - private boolean working;
3.8
3.9 public synchronized void assignPilot(T pilot) {
3.10 assert !working : "Shall not be working yet in order to be consistent";
3.11 this.pilot = pilot;
3.12 }
3.13
3.14 + // BEGIN: reentrant.assert
3.15 + private boolean working;
3.16 public int sumBigger(Collection<T> args) {
3.17 assert !working : "Shall not be working yet in order to be consistent";
3.18 working = true;
3.19 try {
3.20 - for (T cmp : args) {
3.21 - if (pilot.compareTo(cmp) < 0) {
3.22 - cnt++;
3.23 - }
3.24 - }
3.25 - return cnt;
3.26 + return doCriticalSection(args);
3.27 } finally {
3.28 working = false;
3.29 }
3.30 }
3.31 + // END: reentrant.assert
3.32 +
3.33 +
3.34 + private int doCriticalSection(Collection<T> args) {
3.35 + for (T cmp : args) {
3.36 + if (pilot.compareTo(cmp) < 0) {
3.37 + cnt++;
3.38 + }
3.39 + }
3.40 + return cnt;
3.41 + }
3.42
3.43 public int getCount() {
3.44 assert !working : "Shall not be working yet in order to be consistent";
4.1 --- a/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithNonReentrantLock.java Sat Jun 14 09:54:36 2008 +0200
4.2 +++ b/samples/reentrant/src/org/apidesign/reentrant/CriticalSectionSynchronizedWithNonReentrantLock.java Sat Jun 14 09:54:37 2008 +0200
4.3 @@ -7,7 +7,6 @@
4.4 public class CriticalSectionSynchronizedWithNonReentrantLock<T extends Comparable<T>> implements CriticalSection<T> {
4.5 private T pilot;
4.6 private int cnt;
4.7 - private Lock lock = new NonReentrantLock();
4.8
4.9 public void assignPilot(T pilot) {
4.10 lock.lock();
4.11 @@ -18,19 +17,26 @@
4.12 }
4.13 }
4.14
4.15 + // BEGIN: reentrant.nonreentrant.lock
4.16 + private Lock lock = new NonReentrantLock();
4.17 public int sumBigger(Collection<T> args) {
4.18 lock.lock();
4.19 try {
4.20 - for (T cmp : args) {
4.21 - if (pilot.compareTo(cmp) < 0) {
4.22 - cnt++;
4.23 - }
4.24 - }
4.25 - return cnt;
4.26 + return doCriticalSection(args);
4.27 } finally {
4.28 lock.unlock();
4.29 }
4.30 }
4.31 + // END: reentrant.nonreentrant.lock
4.32 +
4.33 + private int doCriticalSection(Collection<T> args) {
4.34 + for (T cmp : args) {
4.35 + if (pilot.compareTo(cmp) < 0) {
4.36 + cnt++;
4.37 + }
4.38 + }
4.39 + return cnt;
4.40 + }
4.41
4.42 public int getCount() {
4.43 lock.lock();
5.1 --- a/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionBase.java Sat Jun 14 09:54:36 2008 +0200
5.2 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionBase.java Sat Jun 14 09:54:37 2008 +0200
5.3 @@ -8,12 +8,17 @@
5.4
5.5 public abstract class CriticalSectionBase {
5.6 protected abstract CriticalSection<Integer> create();
5.7 + protected boolean reentrantJustOnce() {
5.8 + return false;
5.9 + }
5.10
5.11 + // BEGIN: reentrant.ok.call
5.12 @Test
5.13 public void testCriticalSectionWith15() {
5.14 final CriticalSection<Integer> cs = create();
5.15 testFor15(cs);
5.16 }
5.17 + // END: reentrant.ok.call
5.18
5.19 final void testFor15(CriticalSection<Integer> cs) {
5.20 cs.assignPilot(15);
5.21 @@ -41,9 +46,13 @@
5.22 cs.assignPilot(10);
5.23
5.24 class ChangePilotTo15 implements Runnable {
5.25 + // BEGIN: reentrant.forbidden.call
5.26 + // if this runnable is called from inside the critical section,
5.27 + // and the locks are non-reentrant then it throws an exception
5.28 public void run() {
5.29 testFor15(cs);
5.30 }
5.31 + // END: reentrant.forbidden.call
5.32 }
5.33
5.34 List<Integer> ints = new MyCollection(new ChangePilotTo15(), 3);
5.35 @@ -64,7 +73,7 @@
5.36 }
5.37
5.38 class MyCollection extends ArrayList<Integer> {
5.39 - private final Runnable callback;
5.40 + private Runnable callback;
5.41 private final int callbackBeforeIndex;
5.42
5.43 public MyCollection(Runnable callback, int callbackAtIndex) {
5.44 @@ -84,7 +93,12 @@
5.45
5.46 public Integer next() {
5.47 if (index++ == callbackBeforeIndex) {
5.48 - callback.run();
5.49 + if (callback != null) {
5.50 + callback.run();
5.51 + }
5.52 + if (reentrantJustOnce()) {
5.53 + callback = null;
5.54 + }
5.55 }
5.56
5.57 return delegate.next();
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/samples/reentrant/test/org/apidesign/reentrant/CriticalSectionReentrantForLoopTest.java Sat Jun 14 09:54:37 2008 +0200
6.3 @@ -0,0 +1,13 @@
6.4 +package org.apidesign.reentrant;
6.5 +
6.6 +public class CriticalSectionReentrantForLoopTest extends CriticalSectionBase {
6.7 + @Override
6.8 + protected CriticalSection<Integer> create() {
6.9 + return new CriticalSectionReentrantForLoop<Integer>();
6.10 + }
6.11 +
6.12 + @Override
6.13 + protected boolean reentrantJustOnce() {
6.14 + return true;
6.15 + }
6.16 +}
6.17 \ No newline at end of file