16. public class Account{ private int balance; public synchronized int getBalance(){ Return balance; } public synchronized void setBalance(int newBalance){ this.balance = newBalance; } public inc(int delta){ setBalance(getBalance()+delta); } } Not Composable
29. public class Account{ private int balance; public int getBalance(){ Return balance; } public inc(int delta){ if(balance + delta<0) Throw new NotEnoughCashException() this.balance += balance; } } static void transfer(Account from, Account to, int amount){ to.inc(amount); from.inc(-amount); } Not atomic
39. @AtomicObject public class Account{ private int balance; public int getBalance(){ Return balance; } public void inc(int delta){ this.balance += balance; } } @AtomicMethod static void transfer(Account from, Account to, int amount){ from.inc(-amount); to.inc(amount); } Using STM: POJO based
40. @AtomicObject public class Account{ private int balance; @Exclude private int ignore; public int getBalance(){ Return balance; } public void inc(int delta){ this.balance += balance; } } Excluding fields
41.
42.
43.
44. @AtomicObject public class Account{ final Ref<Integer> balance = new Ref<Integer>(); public int getBalance(){ Return balance.get(); } public void inc(int delta){ balance.set(balance.get()+delta); } } @AtomicMethod static void transfer(Account from, Account to, int amount){ from.inc(-amount); to.inc(amount); } Using STM : Managed Ref based
50. @AtomicObject public class Account{ private int balance; public int getBalance(){ Return balance; } public inc(int delta){ this.balance += balance; } } Multiverse: How
51. @AtomicObject public class Account implements AtomicObject{ AtomicReference<Account__Tranlocal> current = New AtomicReference(); public int getBalance(){ Account__Tranlocal a = getTransaction().load(this); return a.balance; } public void inc(int delta){ Account__Tranlocal a = getTransaction().load(this); a.balance+=delta; } public Account__Tranlocal load(long version){..} public boolean lock(Transaction t){..} public void store(Account__Tranlocal tranlocal){...} ... } public class Account__Tranlocal{ long version; Account atomicObject; int balance; } Multiverse: How
59. import java.util.*; final List<String> l = Collections.synchronizedList(new LinkedList()); void add(String item){ l.add(item); } void addAll(String... items){ for(String item:items){ l.add(item); } } Drop in collections - before
60. import java.util.*; import org.multiverse.datastructures.collections.*; final List<String> l = new StrictLinkedBlockingDeque(); void l(String item){ l.add(item); } @AtomicMethod void addAll(String... items){ for(String item:items){ l.add(item); } } Drop in collections - after
61. import java.util.*; import org.multiverse.datastructures.collections.*; final List<String> l1 = new StrictLinkedBlockingDeque(); final List<String> l2 = new StrictLinkedBlockingDeque(); @AtomicMethod void add(String item){ l1.add(item); l2.add(item); } @AtomicMethod void addAll(String... items){ for(String s: items){ add(s); } } Drop in collections – Woohaa
68. @AtomicObject public class IntRef{ private int value; public void set(int newValue){ this.newValue = newValue; } @AtomicMethod(readonly = true) public int get(){ return value; } } Readonly vs Update Transactions
74. @AtomicObject Class IntRef{ int value = 0; @AtomicMethod(retryCount = 100) void inc(){ value++; } } Automatic retrying transactions
75. @AtomicObject Class IntRef{ int value = 0; void inc(){ Transaction t = getTransaction() if(t!=null){ //there already is a transaction value++; }else{ //there is no transaction, lets create one t = stm.startTransaction() int attempt = 1; while(attempt-1 <= 100){ try{ value++; t.commit() }catch(RecoverableException ex){ attempt++; t.abortAndReset(); } } throw new TooManyRetriesException(); } } } Automatic retrying transactions
81. @AtomicObject public class TStack<E>{ private Node<E> head; public void push(E item){ head = new Node<E>(head, item); } public E pop(){ if(head == null){ retry(); } Node<E> oldHead = head; head = head.next; return oldHead.value; } static class Node{ final Node<E> next; final E value; Node(Node<E> next, E value){ this.next = next; this.value = value; } } }
82.
83. TStack<Integer> stack1 = new TStack<Integer>(); TStack<Integer> stack2 = new TStack<Integer>(); @AtomicMethod public int popFromOneOfTheStacks(){ if(!stack1.isEmpty()){ Return stack1.pop(); } if(!stack2.isEmpty()){ Return stack2.pop(); } retry(); return -1;//is never executed }
84.
85. TStack<Integer> stack1 = new TStack<Integer>(); TStack<Integer> stack2 = new TStack<Integer>(); @AtomicMethod public int popFromOneOfTheStacks(){ return new OrElseTemplate<Integer>(){ void runOr(){ return stack1.pop(); } void runElse(){ return stack2.pop(); } }.execute(); }
86. TStack<Integer> stack1 = new TStack<Integer>(); TStack<Integer> stack2 = new TStack<Integer>(); @AtomicMethod public int popFromOneOfTheStacks(){ return new OrElseTemplate<Integer>(){ void runOr(){ return stack1.pop(); } void runElse(){ return stack2.pop(); } }.execute(); }