package org.multiverse.stms.gamma.transactionalobjects.txnlong;
import org.junit.Before;
import org.junit.Test;
import org.multiverse.TestThread;
import org.multiverse.stms.gamma.GammaConstants;
import org.multiverse.stms.gamma.GammaStm;
import org.multiverse.stms.gamma.transactionalobjects.GammaTxnLong;
import org.multiverse.stms.gamma.transactionalobjects.Tranlocal;
import org.multiverse.stms.gamma.transactions.GammaTxn;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.Assert.assertEquals;
import static org.multiverse.TestUtils.*;
public class GammaTxnLong_consistentLoadStressTest implements GammaConstants {
private GammaStm stm;
private volatile boolean stop;
private GammaTxnLong ref;
private final AtomicLong inconsistencyCount = new AtomicLong();
@Before
public void setUp() {
stm = new GammaStm();
stop = false;
ref = new GammaTxnLong(stm, VERSION_UNCOMMITTED + 1);
}
@Test
public void test() {
int readThreadCount = 10;
ReadThread[] readThreads = new ReadThread[readThreadCount];
for (int k = 0; k < readThreads.length; k++) {
readThreads[k] = new ReadThread(k);
}
int writerCount = 2;
UpdateThread[] updateThreads = new UpdateThread[writerCount];
for (int k = 0; k < updateThreads.length; k++) {
updateThreads[k] = new UpdateThread(k);
}
startAll(readThreads);
startAll(updateThreads);
sleepMs(30 * 1000);
stop = true;
joinAll(readThreads);
joinAll(writerCount);
assertEquals(0, inconsistencyCount.get());
}
class ReadThread extends TestThread {
private final GammaTxn tx = stm.newDefaultTxn();
public ReadThread(int id) {
super("ReadThread-" + id);
}
@Override
public void doRun() throws Exception {
Tranlocal tranlocal = new Tranlocal();
int k = 0;
while (!stop) {
boolean success = ref.load(tx, tranlocal, LOCKMODE_NONE, 100, true);
if (success) {
if (tranlocal.version != tranlocal.long_value) {
inconsistencyCount.incrementAndGet();
System.out.printf("Inconsistency detected, version %s and value %s\n", tranlocal.version, tranlocal.long_value);
}
if (tranlocal.hasDepartObligation) {
ref.departAfterReading();
}
}
k++;
if (k % 100000 == 0) {
System.out.printf("%s is at %s\n", getName(), k);
}
}
}
}
class UpdateThread extends TestThread {
public UpdateThread(int id) {
super("UpdateThread-" + id);
}
@Override
public void doRun() throws Exception {
int k = 0;
while (!stop) {
int arriveStatus = ref.arriveAndLock(1, LOCKMODE_EXCLUSIVE);
if (arriveStatus == FAILURE) {
continue;
}
ref.long_value = ref.version + 1;
ref.version = ref.version + 1;
ref.departAfterUpdateAndUnlock();
k++;
if (k % 100000 == 0) {
System.out.printf("%s is at %s\n", getName(), k);
}
}
}
}
}