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 + + + + + + + + + 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 @@ + + + + + + + + + + + +