diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..4d1c805
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+stm-java
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..217af47
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..3572571
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dictionaries/mishadoff.xml b/.idea/dictionaries/mishadoff.xml
new file mode 100644
index 0000000..9d4efda
--- /dev/null
+++ b/.idea/dictionaries/mishadoff.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..e206d70
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/.idea/libraries/multiverse_core_0_7_0.xml b/.idea/libraries/multiverse_core_0_7_0.xml
new file mode 100644
index 0000000..548f518
--- /dev/null
+++ b/.idea/libraries/multiverse_core_0_7_0.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d710ea5
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..b702c67
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml
new file mode 100644
index 0000000..922003b
--- /dev/null
+++ b/.idea/scopes/scope_settings.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 0000000..3b00020
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,125 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..def6a6a
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..2443c77
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,885 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Abstraction issues
+
+
+ Android Lint
+
+
+ Assignment issues
+
+
+ Assignment issuesGroovy
+
+
+ Bitwise operation issues
+
+
+ Class structure
+
+
+ Code maturity issues
+
+
+ Code style issues
+
+
+ Control FlowGroovy
+
+
+ Control flow issues
+
+
+ Error handling
+
+
+ GPath inspectionsGroovy
+
+
+ General
+
+
+ Groovy
+
+
+ HTML
+
+
+ Initialization issues
+
+
+ IntelliJ IDEA Platform Inspections
+
+
+ Internationalization issues
+
+
+ J2ME issues
+
+
+ JUnit issues
+
+
+ Java language level issues
+
+
+ Java language level migration aids
+
+
+ Javadoc issues
+
+
+ Logging issues
+
+
+ Memory issues
+
+
+ Naming ConventionsGroovy
+
+
+ Naming conventions
+
+
+ Numeric issues
+
+
+ Performance issues
+
+
+ Portability issues
+
+
+ Potentially confusing code constructsGroovy
+
+
+ Probable bugs
+
+
+ Probable bugsGroovy
+
+
+ Properties Files
+
+
+ RELAX NG
+
+
+ Security issues
+
+
+ Threading issues
+
+
+ UI Form Problems
+
+
+ Visibility issues
+
+
+ XPath
+
+
+ XSLT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ localhost
+ 5050
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $USER_HOME$/.subversion
+ false
+
+
+
+
+ 1382282854010
+ 1382282854010
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No facets are configured
+
+
+
+
+
+
+
+
+
+
+
+ gs-collections-3.2.0
+
+
+
+
+
+
+
+
+
+
+
+ JDK 1.7_x86
+
+
+
+
+
+
+
+
+
+
+
+ stm-java
+
+
+
+
+
+
+
+
+
+
+
+ JDK 1.8.0
+
+
+
+
+
+
+
+
+
+
+
+ multiverse-core-0.7.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/out/production/stm-java/concurrency/Account.class b/out/production/stm-java/concurrency/Account.class
new file mode 100644
index 0000000..b851c56
Binary files /dev/null and b/out/production/stm-java/concurrency/Account.class differ
diff --git a/out/production/stm-java/concurrency/Bank.class b/out/production/stm-java/concurrency/Bank.class
new file mode 100644
index 0000000..8a72b72
Binary files /dev/null and b/out/production/stm-java/concurrency/Bank.class differ
diff --git a/out/production/stm-java/concurrency/BankThread.class b/out/production/stm-java/concurrency/BankThread.class
new file mode 100644
index 0000000..508dc84
Binary files /dev/null and b/out/production/stm-java/concurrency/BankThread.class differ
diff --git a/out/production/stm-java/concurrency/Runner.class b/out/production/stm-java/concurrency/Runner.class
new file mode 100644
index 0000000..4d72da1
Binary files /dev/null and b/out/production/stm-java/concurrency/Runner.class differ
diff --git a/src/concurrency/stm/Context.java b/src/concurrency/stm/Context.java
new file mode 100644
index 0000000..f9cbe6c
--- /dev/null
+++ b/src/concurrency/stm/Context.java
@@ -0,0 +1,8 @@
+package concurrency.stm;
+
+/**
+ * @author mishadoff
+ */
+public abstract class Context {
+ abstract T get(Ref ref);
+}
diff --git a/src/concurrency/stm/GlobalContext.java b/src/concurrency/stm/GlobalContext.java
new file mode 100644
index 0000000..9dd7b5e
--- /dev/null
+++ b/src/concurrency/stm/GlobalContext.java
@@ -0,0 +1,12 @@
+package concurrency.stm;
+
+/**
+ * @author mishadoff
+ */
+public class GlobalContext extends Context {
+
+ @Override
+ T get(Ref ref) {
+ return ref.value;
+ }
+}
diff --git a/src/concurrency/stm/Ref.java b/src/concurrency/stm/Ref.java
new file mode 100644
index 0000000..bb3c068
--- /dev/null
+++ b/src/concurrency/stm/Ref.java
@@ -0,0 +1,20 @@
+package concurrency.stm;
+
+/**
+ * @author mishadoff
+ */
+public final class Ref {
+ T value;
+
+ public Ref(T value) {
+ this.value = value;
+ }
+
+ public T getValue(Context ctx) {
+ return ctx.get(this);
+ }
+
+ public void setValue(T value, Transaction tx) {
+ tx.set(this, value);
+ }
+}
diff --git a/src/concurrency/stm/STM.java b/src/concurrency/stm/STM.java
new file mode 100644
index 0000000..73b846d
--- /dev/null
+++ b/src/concurrency/stm/STM.java
@@ -0,0 +1,18 @@
+package concurrency.stm;
+
+/**
+ * @author mishadoff
+ */
+public final class STM {
+ private STM() {}
+
+ public static Object commitLock = new Object();
+
+ public static void transaction(TransactionBlock block) {
+ Transaction tx = new Transaction();
+ block.setTx(tx);
+ block.run();
+ tx.commit();
+ }
+
+}
diff --git a/src/concurrency/stm/Transaction.java b/src/concurrency/stm/Transaction.java
new file mode 100644
index 0000000..c57bada
--- /dev/null
+++ b/src/concurrency/stm/Transaction.java
@@ -0,0 +1,37 @@
+package concurrency.stm;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * @author mishadoff
+ */
+public final class Transaction extends Context{
+ private HashMap[ inTxMap = new HashMap<>();
+ private HashSet][ toUpdate = new HashSet<>();
+
+ @Override
+ T get(Ref ref) {
+ if (!inTxMap.containsKey(ref)) {
+ inTxMap.put(ref, ref.value);
+ }
+ return (T)inTxMap.get(ref);
+ }
+
+ void set(Ref ref, T value) {
+ inTxMap.put(ref, value);
+ toUpdate.add(ref);
+ }
+
+ boolean commit() {
+ synchronized (STM.commitLock) {
+ // TODO validate
+ boolean isValid = true;
+
+ for (Ref ref : toUpdate) {
+ ref.value = inTxMap.get(ref);
+ }
+ return isValid;
+ }
+ }
+}
diff --git a/src/concurrency/stm/TransactionBlock.java b/src/concurrency/stm/TransactionBlock.java
new file mode 100644
index 0000000..6c95cca
--- /dev/null
+++ b/src/concurrency/stm/TransactionBlock.java
@@ -0,0 +1,16 @@
+package concurrency.stm;
+
+/**
+ * @author mishadoff
+ */
+public abstract class TransactionBlock implements Runnable {
+ private Transaction tx;
+
+ void setTx(Transaction tx) {
+ this.tx = tx;
+ }
+
+ public Transaction getTx() {
+ return tx;
+ }
+}
diff --git a/src/concurrency/test/Account.java b/src/concurrency/test/Account.java
new file mode 100644
index 0000000..27bb96b
--- /dev/null
+++ b/src/concurrency/test/Account.java
@@ -0,0 +1,17 @@
+package concurrency.test;
+
+public class Account {
+ private long money;
+
+ Account(long initialMoney) {
+ money = initialMoney;
+ }
+
+ public void add(long amount) {
+ money += amount;
+ }
+
+ long getMoney() {
+ return money;
+ }
+}
diff --git a/src/concurrency/test/Bank.java b/src/concurrency/test/Bank.java
new file mode 100644
index 0000000..2d19c83
--- /dev/null
+++ b/src/concurrency/test/Bank.java
@@ -0,0 +1,67 @@
+package concurrency.test;
+
+import concurrency.stm.*;
+
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+public class Bank {
+ private Account[] accounts;
+ private Random random = new Random();
+
+ public Bank() {
+ randomFill();
+ }
+
+ void transfer(Account a1, Account a2, int amount) {
+ a1.add(-amount);
+ a2.add(amount);
+ }
+
+ void transfer(final Ref a1, final Ref a2, final int value) {
+ STM.transaction(new TransactionBlock() {
+ @Override
+ public void run() {
+ Transaction tx = this.getTx();
+ int old1 = a1.getValue(tx);
+ a1.setValue(old1 - value, tx);
+ int old2 = a2.getValue(tx);
+ a2.setValue(old2 + value, tx);
+ }
+ });
+ }
+
+ private void randomFill() {
+ int NUM = 10;
+ accounts = new Account[NUM];
+ for (int i = 0; i < NUM; i++) {
+ accounts[i] = new Account(1000000);
+ }
+ }
+
+ public Account getRandomAccount() {
+ return accounts[random.nextInt(accounts.length)];
+ }
+
+ public int getRandomValue() {
+ return random.nextInt(10);
+ }
+
+ public long sum() {
+ long sum = 0;
+ for (Account a : accounts) sum += a.getMoney();
+ return sum;
+ }
+
+ public void simulate(int threads, int num) throws Exception{
+ ExecutorService service =
+ Executors.newFixedThreadPool(threads);
+ for (int i = 0; i < threads; i++) {
+ service.submit(new BankThread(this, num));
+ }
+ service.shutdown();
+ service.awaitTermination(1, TimeUnit.MINUTES);
+ }
+}
diff --git a/src/concurrency/test/BankThread.java b/src/concurrency/test/BankThread.java
new file mode 100644
index 0000000..b05c111
--- /dev/null
+++ b/src/concurrency/test/BankThread.java
@@ -0,0 +1,20 @@
+package concurrency.test;
+
+public class BankThread implements Runnable {
+ private Bank bank;
+ private int num;
+
+ public BankThread(Bank bank, int num) {
+ this.bank = bank;
+ this.num = num;
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < num; i++) {
+ bank.transfer(bank.getRandomAccount(),
+ bank.getRandomAccount(),
+ bank.getRandomValue());
+ }
+ }
+}
diff --git a/src/concurrency/test/Runner.java b/src/concurrency/test/Runner.java
new file mode 100644
index 0000000..99603c8
--- /dev/null
+++ b/src/concurrency/test/Runner.java
@@ -0,0 +1,10 @@
+package concurrency.test;
+
+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());
+ }
+}
diff --git a/stm-java.iml b/stm-java.iml
new file mode 100644
index 0000000..d5c0743
--- /dev/null
+++ b/stm-java.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
]