*** empty log message ***
[IRC.git] / Robust / Transactions / dstm2 / src / dstm2 / AtomicArray.java
1 package dstm2;
2
3 /*
4  * AtomicArray.java
5  *
6  * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle, Santa
7  * Clara, California 95054, U.S.A.  All rights reserved.  
8  * 
9  * Sun Microsystems, Inc. has intellectual property rights relating to
10  * technology embodied in the product that is described in this
11  * document.  In particular, and without limitation, these
12  * intellectual property rights may include one or more of the
13  * U.S. patents listed at http://www.sun.com/patents and one or more
14  * additional patents or pending patent applications in the U.S. and
15  * in other countries.
16  * 
17  * U.S. Government Rights - Commercial software.
18  * Government users are subject to the Sun Microsystems, Inc. standard
19  * license agreement and applicable provisions of the FAR and its
20  * supplements.  Use is subject to license terms.  Sun, Sun
21  * Microsystems, the Sun logo and Java are trademarks or registered
22  * trademarks of Sun Microsystems, Inc. in the U.S. and other
23  * countries.  
24  * 
25  * This product is covered and controlled by U.S. Export Control laws
26  * and may be subject to the export or import laws in other countries.
27  * Nuclear, missile, chemical biological weapons or nuclear maritime
28  * end uses or end users, whether direct or indirect, are strictly
29  * prohibited.  Export or reexport to countries subject to
30  * U.S. embargo or to entities identified on U.S. export exclusion
31  * lists, including, but not limited to, the denied persons and
32  * specially designated nationals lists is strictly prohibited.
33  */
34
35
36
37 import TransactionalIO.exceptions.AbortedException;
38 import TransactionalIO.exceptions.PanicException;
39 import dstm2.factory.ofree.ReadSet;
40 import java.lang.reflect.Array;
41
42 /**
43  * @author mph
44  */
45 @atomic public class AtomicArray<T> {
46   
47   private final T[] array;
48   private final T[] shadow;
49   private Transaction writer;
50   private ReadSet readers;
51   long version;
52   private final String FORMAT = "Unexpected transaction state: %s";
53   
54   /** Creates a new instance of AtomicArray */
55   public AtomicArray(Class _class, int capacity) {
56     array  = (T[]) Array.newInstance(_class, capacity);
57     shadow = (T[]) Array.newInstance(_class, capacity);
58     writer = Transaction.COMMITTED;
59     readers = new ReadSet();
60     version = 0;
61   }
62   
63   public T get(int i) {
64     Transaction me  = Thread.getTransaction();
65     Transaction other = null;
66     ContentionManager manager = Thread.getContentionManager();
67     while (true) {
68       synchronized (this) {
69         other = openRead(me);
70         if (other == null) {
71           return array[i];
72         }
73       }
74       manager.resolveConflict(me, other);
75     }
76   }
77   
78   public void set(int i, T value) {
79     Transaction me  = Thread.getTransaction();
80     Transaction other = null;
81     ContentionManager manager = Thread.getContentionManager();
82     while (true) {
83       synchronized (this) {
84         other = openWrite(me);
85         if (other == null) {
86           array[i] = value;
87           return;
88         }
89       }
90       manager.resolveConflict(me, other);
91     }
92   }
93   /**
94    * Tries to open object for reading. Returns reference to conflictin transaction, if one exists
95    **/
96   private Transaction openRead(Transaction me) {
97     // not in a transaction
98     if (me == null) {   // restore object if latest writer aborted
99       if (writer.isAborted()) {
100         restore();
101         version++;
102         writer = Transaction.COMMITTED;
103       }
104       return null;
105     }
106     // Am I still active?
107     if (!me.isActive()) {
108       throw new AbortedException();
109     }
110     // Have I already opened this object?
111     if (writer == me) {
112       return null;
113     }
114     switch (writer.getStatus()) {
115       case ACTIVE:
116         return writer;
117       case COMMITTED:
118         break;
119       case ABORTED:
120         restore();
121         version++;
122         break;
123       default:
124         throw new PanicException(FORMAT, writer.getStatus());
125     }
126     writer = Transaction.COMMITTED;
127     readers.add(me);
128     return null;
129   }
130   
131   /**
132    * Tries to open object for reading. Returns reference to conflicting transaction, if one exists
133    **/
134   public Transaction openWrite(Transaction me) {
135     // not in a transaction
136     if (me == null) {   // restore object if latest writer aborted
137       if (writer.isAborted()) {
138         restore();
139         version++;
140         writer = Transaction.COMMITTED;
141       }
142       return null;
143     }
144     if (!me.validate()) {
145       throw new AbortedException();
146     }
147     if (me == writer) {
148       return null;
149     }
150     for (Transaction reader : readers) {
151       if (reader.isActive() && reader != me) {
152         return reader;
153       }
154     }
155     readers.clear();
156     switch (writer.getStatus()) {
157       case ACTIVE:
158         return writer;
159       case COMMITTED:
160         backup();
161         version++;
162         break;
163       case ABORTED:
164         restore();
165         version++;
166         break;
167       default:
168         throw new PanicException(FORMAT, writer.getStatus());
169     }
170     writer = me;
171     return null;
172   }
173   
174   private void restore() {
175     System.arraycopy(shadow, 0, array, 0, array.length);
176   }
177   private void backup() {
178     System.arraycopy(array, 0, shadow, 0, array.length);
179   }
180   
181 }