/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
class Collection1<T> {
private volatile transient int count = 0;
protected synchronized int getCount() {
return count;
}
public void add(T t) {
count++;
}
public void addRange(T[] ts) {
for (T t : ts) { add(t); };
// count = count + ts.length;
}
}
class Collection2<T> extends Collection1<T> {
protected class AddCounter {
int[] addCount = new int[]{-10,-10,-10,-10,-10,-10,-10,-10,-10,-10};
int addLevel = -1;
int checkLevel = 0;
protected void beginAdd() {
addLevel++;
if (addLevel == checkLevel) {
addCount[checkLevel] = 0;
}
}
protected void endAdd() {
if ((addLevel == checkLevel) && (checkLevel > 0)) {
addCount[checkLevel - 1] = addCount[checkLevel - 1] + addCount[checkLevel];
}
addLevel--;
}
protected void completeAdd(int count) {
if (addLevel == checkLevel) {
addCount[checkLevel] = addCount[checkLevel] + count;
}
}
}
protected ThreadLocal<AddCounter> addCounter = new ThreadLocal<AddCounter>() {
@Override
protected AddCounter initialValue() {
return new AddCounter();
}
};
public int getAddCount() {
AddCounter ac = addCounter.get();
return ac.addCount[ac.checkLevel];
}
public void beginAdd() {
AddCounter ac = addCounter.get();
ac.beginAdd();
ac.checkLevel++;
}
public void endAdd() {
AddCounter ac = addCounter.get();
ac.checkLevel--;
ac.endAdd();
}
@Override
public void add(T t) {
AddCounter ac = addCounter.get();
ac.beginAdd();
try {
super.add(t);
ac.completeAdd(1);
} finally {
ac.endAdd();
}
}
@Override
public void addRange(T[] ts) {
AddCounter ac = addCounter.get();
ac.beginAdd();
try {
super.addRange(ts);
ac.completeAdd(ts.length);
} finally {
ac.endAdd();
}
}
}
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static boolean sleep2(int value) {
try {
return false;
return true;
}
}
{
Collection2<Object> cc;
cc = new Collection2<>();
@Override
public void run() {
cc.add(null);
if (sleep2(10)) { return; }
System.
out.
println("tr1: Count = " + cc.
getCount() + ", add count = " + cc.
getAddCount()); }
});
@Override
public void run() {
if (sleep2(10)) { return; }
if (sleep2(10)) { return; }
System.
out.
println("tr2: Count = " + cc.
getCount() + ", add count = " + cc.
getAddCount()); }
});
@Override
public void run() {
cc.beginAdd();
try {
cc.beginAdd();
try {
if (sleep2(10)) { return; }
cc.add(null);
if (sleep2(10)) { return; }
cc.add(null);
} finally {
cc.endAdd();
}
System.
out.
println("tr3 2: Count = " + cc.
getCount() + ", add count = " + cc.
getAddCount()); if (sleep2(10)) { return; }
} finally {
cc.endAdd();
}
System.
out.
println("tr3 1: Count = " + cc.
getCount() + ", add count = " + cc.
getAddCount()); }
});
t3.start();
t2.start();
t1.start();
}
}