1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.melati.poem.transaction;
47
48 import org.melati.poem.PoemBugPoemException;
49
50
51
52
53 public abstract class Transactioned {
54
55 protected boolean valid = true;
56
57
58 private int seenMask = 0;
59
60
61 private Transaction touchedBy = null;
62 private TransactionPool transactionPool = null;
63
64
65
66
67
68 public Transactioned(TransactionPool transactionPool) {
69 this.transactionPool = transactionPool;
70 }
71
72
73
74
75 public Transactioned() {
76 this(null);
77 }
78
79
80
81
82 protected abstract void load(Transaction transaction);
83
84
85
86
87
88
89
90
91
92 protected abstract boolean upToDate(Transaction transaction);
93
94 protected abstract void writeDown(Transaction transaction);
95
96 protected synchronized void reset() {
97 valid = true;
98 seenMask = 0;
99 touchedBy = null;
100 }
101
102 protected final TransactionPool transactionPool() {
103 return transactionPool;
104 }
105
106 protected synchronized void setTransactionPool(
107 TransactionPool transactionPool) {
108 if (transactionPool == null)
109 throw new NullPointerException();
110 if (this.transactionPool != null &&
111 this.transactionPool != transactionPool)
112 throw new IllegalArgumentException();
113
114 this.transactionPool = transactionPool;
115 }
116
117
118
119
120
121
122 private void ensureValid(Transaction transaction) {
123 if (!valid) {
124 if (transaction == null)
125 transaction = touchedBy;
126
127
128
129 if (!upToDate(transaction))
130 load(transaction);
131
132 valid = true;
133 }
134 }
135
136 protected void readLock(Transaction transaction) {
137
138 if (transaction != null) {
139
140
141 for (;;) {
142 Transaction blocker;
143 synchronized (this) {
144 if (touchedBy != null && touchedBy != transaction)
145 blocker = touchedBy;
146 else {
147 if ((seenMask & transaction.mask) == 0) {
148 seenMask |= transaction.mask;
149 transaction.notifySeen(this);
150 }
151 break;
152 }
153 }
154
155 blocker.block(transaction);
156 }
157 }
158
159 ensureValid(transaction);
160 }
161
162
163
164
165
166
167
168
169
170
171
172 protected void writeLock(Transaction transaction) {
173
174 if (transaction == null)
175 throw new WriteCommittedException(this);
176
177
178
179 for (;;) {
180 Transaction blocker = null;
181 synchronized (this) {
182 if (touchedBy == transaction)
183
184 break;
185
186 else if (touchedBy != null)
187
188 blocker = touchedBy;
189
190 else {
191 int othersSeenMask = seenMask & transaction.negMask;
192 if (othersSeenMask == 0) {
193
194
195 touchedBy = transaction;
196 transaction.notifyTouched(this);
197 break;
198 }
199 else {
200
201
202
203
204
205
206
207 int m = transactionPool().transactionsMax();
208 int t, mask;
209 for (t = 0, mask = 1;
210 t < m && (othersSeenMask & mask) == 0;
211 ++t, mask <<= 1)
212 ;
213
214 if (t == m)
215 throw new PoemBugPoemException(
216 "Thought there was a blocking transaction, " +
217 "but didn't find it");
218
219 blocker = transactionPool().transaction(t);
220 }
221 }
222 }
223
224 blocker.block(transaction);
225 }
226
227 ensureValid(transaction);
228 }
229
230 protected synchronized void commit(Transaction transaction) {
231 if (touchedBy != transaction)
232 throw new CrossTransactionCommitException(this);
233 touchedBy = null;
234 }
235
236 protected synchronized void rollback(Transaction transaction) {
237 if (touchedBy != transaction)
238 throw new CrossTransactionCommitException(this);
239 touchedBy = null;
240 valid = false;
241 }
242
243
244
245
246 public synchronized void invalidate() {
247 valid = false;
248 }
249
250
251
252
253 public synchronized void markValid() {
254 valid = true;
255 }
256
257 protected synchronized void unSee(Transaction transaction) {
258 seenMask &= transaction.negMask;
259 }
260 }