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 Jan 1, 2009 */
|
rlm@10
|
12
|
rlm@10
|
13 package clojure.lang;
|
rlm@10
|
14
|
rlm@10
|
15 import java.util.concurrent.atomic.AtomicReference;
|
rlm@10
|
16
|
rlm@10
|
17 final public class Atom extends ARef{
|
rlm@10
|
18 final AtomicReference state;
|
rlm@10
|
19
|
rlm@10
|
20 public Atom(Object state){
|
rlm@10
|
21 this.state = new AtomicReference(state);
|
rlm@10
|
22 }
|
rlm@10
|
23
|
rlm@10
|
24 public Atom(Object state, IPersistentMap meta){
|
rlm@10
|
25 super(meta);
|
rlm@10
|
26 this.state = new AtomicReference(state);
|
rlm@10
|
27 }
|
rlm@10
|
28
|
rlm@10
|
29 public Object deref(){
|
rlm@10
|
30 return state.get();
|
rlm@10
|
31 }
|
rlm@10
|
32
|
rlm@10
|
33 public Object swap(IFn f) throws Exception{
|
rlm@10
|
34 for(; ;)
|
rlm@10
|
35 {
|
rlm@10
|
36 Object v = deref();
|
rlm@10
|
37 Object newv = f.invoke(v);
|
rlm@10
|
38 validate(newv);
|
rlm@10
|
39 if(state.compareAndSet(v, newv))
|
rlm@10
|
40 {
|
rlm@10
|
41 notifyWatches(v, newv);
|
rlm@10
|
42 return newv;
|
rlm@10
|
43 }
|
rlm@10
|
44 }
|
rlm@10
|
45 }
|
rlm@10
|
46
|
rlm@10
|
47 public Object swap(IFn f, Object arg) throws Exception{
|
rlm@10
|
48 for(; ;)
|
rlm@10
|
49 {
|
rlm@10
|
50 Object v = deref();
|
rlm@10
|
51 Object newv = f.invoke(v, arg);
|
rlm@10
|
52 validate(newv);
|
rlm@10
|
53 if(state.compareAndSet(v, newv))
|
rlm@10
|
54 {
|
rlm@10
|
55 notifyWatches(v, newv);
|
rlm@10
|
56 return newv;
|
rlm@10
|
57 }
|
rlm@10
|
58 }
|
rlm@10
|
59 }
|
rlm@10
|
60
|
rlm@10
|
61 public Object swap(IFn f, Object arg1, Object arg2) throws Exception{
|
rlm@10
|
62 for(; ;)
|
rlm@10
|
63 {
|
rlm@10
|
64 Object v = deref();
|
rlm@10
|
65 Object newv = f.invoke(v, arg1, arg2);
|
rlm@10
|
66 validate(newv);
|
rlm@10
|
67 if(state.compareAndSet(v, newv))
|
rlm@10
|
68 {
|
rlm@10
|
69 notifyWatches(v, newv);
|
rlm@10
|
70 return newv;
|
rlm@10
|
71 }
|
rlm@10
|
72 }
|
rlm@10
|
73 }
|
rlm@10
|
74
|
rlm@10
|
75 public Object swap(IFn f, Object x, Object y, ISeq args) throws Exception{
|
rlm@10
|
76 for(; ;)
|
rlm@10
|
77 {
|
rlm@10
|
78 Object v = deref();
|
rlm@10
|
79 Object newv = f.applyTo(RT.listStar(v, x, y, args));
|
rlm@10
|
80 validate(newv);
|
rlm@10
|
81 if(state.compareAndSet(v, newv))
|
rlm@10
|
82 {
|
rlm@10
|
83 notifyWatches(v, newv);
|
rlm@10
|
84 return newv;
|
rlm@10
|
85 }
|
rlm@10
|
86 }
|
rlm@10
|
87 }
|
rlm@10
|
88
|
rlm@10
|
89 public boolean compareAndSet(Object oldv, Object newv){
|
rlm@10
|
90 validate(newv);
|
rlm@10
|
91 boolean ret = state.compareAndSet(oldv, newv);
|
rlm@10
|
92 if(ret)
|
rlm@10
|
93 notifyWatches(oldv, newv);
|
rlm@10
|
94 return ret;
|
rlm@10
|
95 }
|
rlm@10
|
96
|
rlm@10
|
97 public Object reset(Object newval){
|
rlm@10
|
98 Object oldval = state.get();
|
rlm@10
|
99 validate(newval);
|
rlm@10
|
100 state.set(newval);
|
rlm@10
|
101 notifyWatches(oldval, newval);
|
rlm@10
|
102 return newval;
|
rlm@10
|
103 }
|
rlm@10
|
104 }
|