rlm@10
|
1 /**
|
rlm@10
|
2 * Copyright (c) Rich Hickey. All rights reserved.
|
rlm@10
|
3 * The use and distribution terms for this software are covered by the
|
rlm@10
|
4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
rlm@10
|
5 * which can be found in the file epl-v10.html at the root of this distribution.
|
rlm@10
|
6 * By using this software in any fashion, you are agreeing to be bound by
|
rlm@10
|
7 * the terms of this license.
|
rlm@10
|
8 * You must not remove this notice, or any other, from this software.
|
rlm@10
|
9 **/
|
rlm@10
|
10
|
rlm@10
|
11 /* rich Jul 25, 2007 */
|
rlm@10
|
12
|
rlm@10
|
13 package clojure.lang;
|
rlm@10
|
14
|
rlm@10
|
15 import java.util.concurrent.atomic.AtomicInteger;
|
rlm@10
|
16 import java.util.concurrent.atomic.AtomicLong;
|
rlm@10
|
17 import java.util.concurrent.locks.ReentrantReadWriteLock;
|
rlm@10
|
18
|
rlm@10
|
19 public class Ref extends ARef implements IFn, Comparable<Ref>, IRef{
|
rlm@10
|
20 public int compareTo(Ref ref) {
|
rlm@10
|
21 if(this.id == ref.id)
|
rlm@10
|
22 return 0;
|
rlm@10
|
23 else if(this.id < ref.id)
|
rlm@10
|
24 return -1;
|
rlm@10
|
25 else
|
rlm@10
|
26 return 1;
|
rlm@10
|
27 }
|
rlm@10
|
28
|
rlm@10
|
29 public int getMinHistory(){
|
rlm@10
|
30 return minHistory;
|
rlm@10
|
31 }
|
rlm@10
|
32
|
rlm@10
|
33 public Ref setMinHistory(int minHistory){
|
rlm@10
|
34 this.minHistory = minHistory;
|
rlm@10
|
35 return this;
|
rlm@10
|
36 }
|
rlm@10
|
37
|
rlm@10
|
38 public int getMaxHistory(){
|
rlm@10
|
39 return maxHistory;
|
rlm@10
|
40 }
|
rlm@10
|
41
|
rlm@10
|
42 public Ref setMaxHistory(int maxHistory){
|
rlm@10
|
43 this.maxHistory = maxHistory;
|
rlm@10
|
44 return this;
|
rlm@10
|
45 }
|
rlm@10
|
46
|
rlm@10
|
47 public static class TVal{
|
rlm@10
|
48 Object val;
|
rlm@10
|
49 long point;
|
rlm@10
|
50 long msecs;
|
rlm@10
|
51 TVal prior;
|
rlm@10
|
52 TVal next;
|
rlm@10
|
53
|
rlm@10
|
54 TVal(Object val, long point, long msecs, TVal prior){
|
rlm@10
|
55 this.val = val;
|
rlm@10
|
56 this.point = point;
|
rlm@10
|
57 this.msecs = msecs;
|
rlm@10
|
58 this.prior = prior;
|
rlm@10
|
59 this.next = prior.next;
|
rlm@10
|
60 this.prior.next = this;
|
rlm@10
|
61 this.next.prior = this;
|
rlm@10
|
62 }
|
rlm@10
|
63
|
rlm@10
|
64 TVal(Object val, long point, long msecs){
|
rlm@10
|
65 this.val = val;
|
rlm@10
|
66 this.point = point;
|
rlm@10
|
67 this.msecs = msecs;
|
rlm@10
|
68 this.next = this;
|
rlm@10
|
69 this.prior = this;
|
rlm@10
|
70 }
|
rlm@10
|
71
|
rlm@10
|
72 }
|
rlm@10
|
73
|
rlm@10
|
74 TVal tvals;
|
rlm@10
|
75 final AtomicInteger faults;
|
rlm@10
|
76 final ReentrantReadWriteLock lock;
|
rlm@10
|
77 LockingTransaction.Info tinfo;
|
rlm@10
|
78 //IFn validator;
|
rlm@10
|
79 final long id;
|
rlm@10
|
80
|
rlm@10
|
81 volatile int minHistory = 0;
|
rlm@10
|
82 volatile int maxHistory = 10;
|
rlm@10
|
83
|
rlm@10
|
84 static final AtomicLong ids = new AtomicLong();
|
rlm@10
|
85
|
rlm@10
|
86 public Ref(Object initVal) throws Exception{
|
rlm@10
|
87 this(initVal, null);
|
rlm@10
|
88 }
|
rlm@10
|
89
|
rlm@10
|
90 public Ref(Object initVal,IPersistentMap meta) throws Exception{
|
rlm@10
|
91 super(meta);
|
rlm@10
|
92 this.id = ids.getAndIncrement();
|
rlm@10
|
93 this.faults = new AtomicInteger();
|
rlm@10
|
94 this.lock = new ReentrantReadWriteLock();
|
rlm@10
|
95 tvals = new TVal(initVal, 0, System.currentTimeMillis());
|
rlm@10
|
96 }
|
rlm@10
|
97
|
rlm@10
|
98 //the latest val
|
rlm@10
|
99
|
rlm@10
|
100 // ok out of transaction
|
rlm@10
|
101 Object currentVal(){
|
rlm@10
|
102 try
|
rlm@10
|
103 {
|
rlm@10
|
104 lock.readLock().lock();
|
rlm@10
|
105 if(tvals != null)
|
rlm@10
|
106 return tvals.val;
|
rlm@10
|
107 throw new IllegalStateException(this.toString() + " is unbound.");
|
rlm@10
|
108 }
|
rlm@10
|
109 finally
|
rlm@10
|
110 {
|
rlm@10
|
111 lock.readLock().unlock();
|
rlm@10
|
112 }
|
rlm@10
|
113 }
|
rlm@10
|
114
|
rlm@10
|
115 //*
|
rlm@10
|
116
|
rlm@10
|
117 public Object deref(){
|
rlm@10
|
118 LockingTransaction t = LockingTransaction.getRunning();
|
rlm@10
|
119 if(t == null)
|
rlm@10
|
120 return currentVal();
|
rlm@10
|
121 return t.doGet(this);
|
rlm@10
|
122 }
|
rlm@10
|
123
|
rlm@10
|
124 //void validate(IFn vf, Object val){
|
rlm@10
|
125 // try{
|
rlm@10
|
126 // if(vf != null && !RT.booleanCast(vf.invoke(val)))
|
rlm@10
|
127 // throw new IllegalStateException("Invalid ref state");
|
rlm@10
|
128 // }
|
rlm@10
|
129 // catch(RuntimeException re)
|
rlm@10
|
130 // {
|
rlm@10
|
131 // throw re;
|
rlm@10
|
132 // }
|
rlm@10
|
133 // catch(Exception e)
|
rlm@10
|
134 // {
|
rlm@10
|
135 // throw new IllegalStateException("Invalid ref state", e);
|
rlm@10
|
136 // }
|
rlm@10
|
137 //}
|
rlm@10
|
138 //
|
rlm@10
|
139 //public void setValidator(IFn vf){
|
rlm@10
|
140 // try
|
rlm@10
|
141 // {
|
rlm@10
|
142 // lock.writeLock().lock();
|
rlm@10
|
143 // validate(vf,currentVal());
|
rlm@10
|
144 // validator = vf;
|
rlm@10
|
145 // }
|
rlm@10
|
146 // finally
|
rlm@10
|
147 // {
|
rlm@10
|
148 // lock.writeLock().unlock();
|
rlm@10
|
149 // }
|
rlm@10
|
150 //}
|
rlm@10
|
151 //
|
rlm@10
|
152 //public IFn getValidator(){
|
rlm@10
|
153 // try
|
rlm@10
|
154 // {
|
rlm@10
|
155 // lock.readLock().lock();
|
rlm@10
|
156 // return validator;
|
rlm@10
|
157 // }
|
rlm@10
|
158 // finally
|
rlm@10
|
159 // {
|
rlm@10
|
160 // lock.readLock().unlock();
|
rlm@10
|
161 // }
|
rlm@10
|
162 //}
|
rlm@10
|
163
|
rlm@10
|
164 public Object set(Object val){
|
rlm@10
|
165 return LockingTransaction.getEx().doSet(this, val);
|
rlm@10
|
166 }
|
rlm@10
|
167
|
rlm@10
|
168 public Object commute(IFn fn, ISeq args) throws Exception{
|
rlm@10
|
169 return LockingTransaction.getEx().doCommute(this, fn, args);
|
rlm@10
|
170 }
|
rlm@10
|
171
|
rlm@10
|
172 public Object alter(IFn fn, ISeq args) throws Exception{
|
rlm@10
|
173 LockingTransaction t = LockingTransaction.getEx();
|
rlm@10
|
174 return t.doSet(this, fn.applyTo(RT.cons(t.doGet(this), args)));
|
rlm@10
|
175 }
|
rlm@10
|
176
|
rlm@10
|
177 public void touch(){
|
rlm@10
|
178 LockingTransaction.getEx().doEnsure(this);
|
rlm@10
|
179 }
|
rlm@10
|
180
|
rlm@10
|
181 //*/
|
rlm@10
|
182 boolean isBound(){
|
rlm@10
|
183 try
|
rlm@10
|
184 {
|
rlm@10
|
185 lock.readLock().lock();
|
rlm@10
|
186 return tvals != null;
|
rlm@10
|
187 }
|
rlm@10
|
188 finally
|
rlm@10
|
189 {
|
rlm@10
|
190 lock.readLock().unlock();
|
rlm@10
|
191 }
|
rlm@10
|
192 }
|
rlm@10
|
193
|
rlm@10
|
194
|
rlm@10
|
195 public void trimHistory(){
|
rlm@10
|
196 try
|
rlm@10
|
197 {
|
rlm@10
|
198 lock.writeLock().lock();
|
rlm@10
|
199 if(tvals != null)
|
rlm@10
|
200 {
|
rlm@10
|
201 tvals.next = tvals;
|
rlm@10
|
202 tvals.prior = tvals;
|
rlm@10
|
203 }
|
rlm@10
|
204 }
|
rlm@10
|
205 finally
|
rlm@10
|
206 {
|
rlm@10
|
207 lock.writeLock().unlock();
|
rlm@10
|
208 }
|
rlm@10
|
209 }
|
rlm@10
|
210
|
rlm@10
|
211 public int getHistoryCount(){
|
rlm@10
|
212 try
|
rlm@10
|
213 {
|
rlm@10
|
214 lock.writeLock().lock();
|
rlm@10
|
215 return histCount();
|
rlm@10
|
216 }
|
rlm@10
|
217 finally
|
rlm@10
|
218 {
|
rlm@10
|
219 lock.writeLock().unlock();
|
rlm@10
|
220 }
|
rlm@10
|
221 }
|
rlm@10
|
222
|
rlm@10
|
223 int histCount(){
|
rlm@10
|
224 if(tvals == null)
|
rlm@10
|
225 return 0;
|
rlm@10
|
226 else
|
rlm@10
|
227 {
|
rlm@10
|
228 int count = 0;
|
rlm@10
|
229 for(TVal tv = tvals.next;tv != tvals;tv = tv.next)
|
rlm@10
|
230 count++;
|
rlm@10
|
231 return count;
|
rlm@10
|
232 }
|
rlm@10
|
233 }
|
rlm@10
|
234
|
rlm@10
|
235 final public IFn fn(){
|
rlm@10
|
236 return (IFn) deref();
|
rlm@10
|
237 }
|
rlm@10
|
238
|
rlm@10
|
239 public Object call() throws Exception{
|
rlm@10
|
240 return invoke();
|
rlm@10
|
241 }
|
rlm@10
|
242
|
rlm@10
|
243 public void run(){
|
rlm@10
|
244 try
|
rlm@10
|
245 {
|
rlm@10
|
246 invoke();
|
rlm@10
|
247 }
|
rlm@10
|
248 catch(Exception e)
|
rlm@10
|
249 {
|
rlm@10
|
250 throw new RuntimeException(e);
|
rlm@10
|
251 }
|
rlm@10
|
252 }
|
rlm@10
|
253
|
rlm@10
|
254 public Object invoke() throws Exception{
|
rlm@10
|
255 return fn().invoke();
|
rlm@10
|
256 }
|
rlm@10
|
257
|
rlm@10
|
258 public Object invoke(Object arg1) throws Exception{
|
rlm@10
|
259 return fn().invoke(arg1);
|
rlm@10
|
260 }
|
rlm@10
|
261
|
rlm@10
|
262 public Object invoke(Object arg1, Object arg2) throws Exception{
|
rlm@10
|
263 return fn().invoke(arg1, arg2);
|
rlm@10
|
264 }
|
rlm@10
|
265
|
rlm@10
|
266 public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception{
|
rlm@10
|
267 return fn().invoke(arg1, arg2, arg3);
|
rlm@10
|
268 }
|
rlm@10
|
269
|
rlm@10
|
270 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception{
|
rlm@10
|
271 return fn().invoke(arg1, arg2, arg3, arg4);
|
rlm@10
|
272 }
|
rlm@10
|
273
|
rlm@10
|
274 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) throws Exception{
|
rlm@10
|
275 return fn().invoke(arg1, arg2, arg3, arg4, arg5);
|
rlm@10
|
276 }
|
rlm@10
|
277
|
rlm@10
|
278 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) throws Exception{
|
rlm@10
|
279 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6);
|
rlm@10
|
280 }
|
rlm@10
|
281
|
rlm@10
|
282 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7)
|
rlm@10
|
283 throws Exception{
|
rlm@10
|
284 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
rlm@10
|
285 }
|
rlm@10
|
286
|
rlm@10
|
287 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
288 Object arg8) throws Exception{
|
rlm@10
|
289 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
rlm@10
|
290 }
|
rlm@10
|
291
|
rlm@10
|
292 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
293 Object arg8, Object arg9) throws Exception{
|
rlm@10
|
294 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
|
rlm@10
|
295 }
|
rlm@10
|
296
|
rlm@10
|
297 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
298 Object arg8, Object arg9, Object arg10) throws Exception{
|
rlm@10
|
299 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
|
rlm@10
|
300 }
|
rlm@10
|
301
|
rlm@10
|
302 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
303 Object arg8, Object arg9, Object arg10, Object arg11) throws Exception{
|
rlm@10
|
304 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11);
|
rlm@10
|
305 }
|
rlm@10
|
306
|
rlm@10
|
307 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
308 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) throws Exception{
|
rlm@10
|
309 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12);
|
rlm@10
|
310 }
|
rlm@10
|
311
|
rlm@10
|
312 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
313 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13)
|
rlm@10
|
314 throws Exception{
|
rlm@10
|
315 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13);
|
rlm@10
|
316 }
|
rlm@10
|
317
|
rlm@10
|
318 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
319 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14)
|
rlm@10
|
320 throws Exception{
|
rlm@10
|
321 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14);
|
rlm@10
|
322 }
|
rlm@10
|
323
|
rlm@10
|
324 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
325 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
326 Object arg15) throws Exception{
|
rlm@10
|
327 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15);
|
rlm@10
|
328 }
|
rlm@10
|
329
|
rlm@10
|
330 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
331 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
332 Object arg15, Object arg16) throws Exception{
|
rlm@10
|
333 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,
|
rlm@10
|
334 arg16);
|
rlm@10
|
335 }
|
rlm@10
|
336
|
rlm@10
|
337 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
338 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
339 Object arg15, Object arg16, Object arg17) throws Exception{
|
rlm@10
|
340 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,
|
rlm@10
|
341 arg16, arg17);
|
rlm@10
|
342 }
|
rlm@10
|
343
|
rlm@10
|
344 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
345 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
346 Object arg15, Object arg16, Object arg17, Object arg18) throws Exception{
|
rlm@10
|
347 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,
|
rlm@10
|
348 arg16, arg17, arg18);
|
rlm@10
|
349 }
|
rlm@10
|
350
|
rlm@10
|
351 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
352 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
353 Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) throws Exception{
|
rlm@10
|
354 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,
|
rlm@10
|
355 arg16, arg17, arg18, arg19);
|
rlm@10
|
356 }
|
rlm@10
|
357
|
rlm@10
|
358 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
359 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
360 Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20)
|
rlm@10
|
361 throws Exception{
|
rlm@10
|
362 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,
|
rlm@10
|
363 arg16, arg17, arg18, arg19, arg20);
|
rlm@10
|
364 }
|
rlm@10
|
365
|
rlm@10
|
366 public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7,
|
rlm@10
|
367 Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14,
|
rlm@10
|
368 Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20,
|
rlm@10
|
369 Object... args)
|
rlm@10
|
370 throws Exception{
|
rlm@10
|
371 return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,
|
rlm@10
|
372 arg16, arg17, arg18, arg19, arg20, args);
|
rlm@10
|
373 }
|
rlm@10
|
374
|
rlm@10
|
375 public Object applyTo(ISeq arglist) throws Exception{
|
rlm@10
|
376 return AFn.applyToHelper(this, arglist);
|
rlm@10
|
377 }
|
rlm@10
|
378
|
rlm@10
|
379 }
|