Skip to content

Commit

Permalink
First REAL working of STM, *fast enough*
Browse files Browse the repository at this point in the history
  • Loading branch information
mishadoff committed Oct 27, 2013
1 parent 695f8ea commit 9db1d4c
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 34 deletions.
17 changes: 1 addition & 16 deletions src/concurrency/stm/GlobalContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*/
public final class GlobalContext extends Context {
private static GlobalContext instance = new GlobalContext();
private HashMap<Ref, Object> world = new HashMap<>();

private GlobalContext() { }

Expand All @@ -18,20 +17,6 @@ public static GlobalContext get() {

@Override
<T> T get(Ref<T> ref) {
return (T)world.get(ref);
}

public void fillSnapshot(final HashMap<Ref, Object> inTxMap,
final HashMap<Ref, Long> version) {
synchronized (STM.snapshotLock) {
for (Map.Entry<Ref, Object> refEntry : world.entrySet()) {
inTxMap.put(refEntry.getKey(), refEntry.getValue());
version.put(refEntry.getKey(), refEntry.getKey().revision);
}
}
}

public <T> void register(Ref<T> ref, T value) {
world.put(ref, value);
return ref.content.value;
}
}
6 changes: 2 additions & 4 deletions src/concurrency/stm/Ref.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
* @author mishadoff
*/
public final class Ref<T> {
T value;
long revision = 0;
RefTuple<T, Long> content;

public Ref(T value) {
this.value = value;
GlobalContext.get().register(this, value);
content = RefTuple.get(value, 0);
}

public T getValue(Context ctx) {
Expand Down
18 changes: 18 additions & 0 deletions src/concurrency/stm/RefTuple.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package concurrency.stm;

/**
* @author mishadoff
*/
public class RefTuple<V, R> {
V value;
R revision;

public RefTuple(V v, R r) {
this.value = v;
this.revision = r;
}

static <V, R> RefTuple get(V v, R r) {
return new RefTuple<V, R>(v, r);
}
}
3 changes: 1 addition & 2 deletions src/concurrency/stm/STM.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
public final class STM {
private STM() {}

public static Object snapshotLock = new Object();
public static Object commitLock = new Object();
public static final Object commitLock = new Object();

public static void transaction(TransactionBlock block) {
boolean committed = false;
Expand Down
16 changes: 11 additions & 5 deletions src/concurrency/stm/Transaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
Expand All @@ -18,19 +19,25 @@ public final class Transaction extends Context{

Transaction() {
revision = transactionNum.incrementAndGet();
GlobalContext.get().fillSnapshot(inTxMap, version);
}

@Override
<T> T get(Ref<T> ref) {
if (!inTxMap.containsKey(ref)) {
RefTuple<T, Long> tuple = ref.content;
inTxMap.put(ref, tuple.value);
if (!version.containsKey(ref)) {
version.put(ref, tuple.revision);
}
}
return (T)inTxMap.get(ref);
}

<T> void set(Ref<T> ref, T value) {
inTxMap.put(ref, value);
toUpdate.add(ref);
if (!version.containsKey(ref)) {
version.put(ref, ref.revision);
version.put(ref, ref.content.revision);
}
}

Expand All @@ -39,7 +46,7 @@ boolean commit() {
// validation
boolean isValid = true;
for (Ref ref : inTxMap.keySet()) {
if (ref.revision != version.get(ref)) {
if (ref.content.revision != version.get(ref)) {
isValid = false;
break;
}
Expand All @@ -48,8 +55,7 @@ boolean commit() {
// writes
if (isValid) {
for (Ref ref : toUpdate) {
ref.value = inTxMap.get(ref);
ref.revision = revision;
ref.content = RefTuple.get(inTxMap.get(ref), revision);
}
}
return isValid;
Expand Down
12 changes: 9 additions & 3 deletions src/concurrency/test/Bank.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public Bank() {
randomFill();
}

void transfer(Account a1, Account a2, int amount) {
synchronized void transfer(Account a1, Account a2, int amount) {
a1.add(-amount);
a2.add(amount);
}
Expand All @@ -34,10 +34,10 @@ public void run() {
}

private void randomFill() {
int NUM = 10;
int NUM = 100;
accounts = new Account[NUM];
for (int i = 0; i < NUM; i++) {
accounts[i] = new Account(1000000);
accounts[i] = new Account(10000);
}
}

Expand All @@ -50,6 +50,12 @@ public int getRandomValue() {
}

public long sum() {
long sum = 0;
for (Account a : accounts) sum += a.getMoney();
return sum;
}

public long sumSTM() {
long sum = 0;
for (Account a : accounts) sum += a.getRef().getValue(GlobalContext.get());
return sum;
Expand Down
2 changes: 1 addition & 1 deletion src/concurrency/test/RefTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static void main(String[] args) {

Bank bank = new Bank();

bank.transferSTM(a, a, 10);
bank.transferSTM(a, b, 10);

System.out.println("A: " + a.getRef().getValue(GlobalContext.get()));
System.out.println("B: " + b.getRef().getValue(GlobalContext.get()));
Expand Down
9 changes: 6 additions & 3 deletions src/concurrency/test/Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
public class Runner {
public static void main(String[] args) throws Exception{
Bank bank = new Bank();
System.out.println("Bank sum before: " + bank.sum());
bank.simulate(100, 100000);
System.out.println("Bank sum after: " + bank.sum());
System.out.println("Bank sum before: " + bank.sumSTM());
long before = System.currentTimeMillis();
bank.simulate(10, 100000);
long after = System.currentTimeMillis();
System.out.println("Bank sum after: " + bank.sumSTM());
System.out.println("Elapsed time: " + (after - before));
}
}

0 comments on commit 9db1d4c

Please sign in to comment.