view src/clojure/lang/ARef.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line source
1 /**
2 * Copyright (c) Rich Hickey. All rights reserved.
3 * The use and distribution terms for this software are covered by the
4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
5 * which can be found in the file epl-v10.html at the root of this distribution.
6 * By using this software in any fashion, you are agreeing to be bound by
7 * the terms of this license.
8 * You must not remove this notice, or any other, from this software.
9 **/
11 /* rich Jan 1, 2009 */
13 package clojure.lang;
15 import java.util.Map;
17 public abstract class ARef extends AReference implements IRef{
18 protected volatile IFn validator = null;
19 private volatile IPersistentMap watches = PersistentHashMap.EMPTY;
21 public ARef(){
22 super();
23 }
25 public ARef(IPersistentMap meta){
26 super(meta);
27 }
29 void validate(IFn vf, Object val){
30 try
31 {
32 if(vf != null && !RT.booleanCast(vf.invoke(val)))
33 throw new IllegalStateException("Invalid reference state");
34 }
35 catch(RuntimeException re)
36 {
37 throw re;
38 }
39 catch(Exception e)
40 {
41 throw new IllegalStateException("Invalid reference state", e);
42 }
43 }
45 void validate(Object val){
46 validate(validator, val);
47 }
49 public void setValidator(IFn vf){
50 try
51 {
52 validate(vf, deref());
53 }
54 catch(Exception e)
55 {
56 throw new RuntimeException(e);
57 }
58 validator = vf;
59 }
61 public IFn getValidator(){
62 return validator;
63 }
65 public IPersistentMap getWatches(){
66 return watches;
67 }
69 synchronized public IRef addWatch(Object key, IFn callback){
70 watches = watches.assoc(key, callback);
71 return this;
72 }
74 synchronized public IRef removeWatch(Object key){
75 try
76 {
77 watches = watches.without(key);
78 }
79 catch(Exception e)
80 {
81 throw new RuntimeException(e);
82 }
84 return this;
85 }
87 public void notifyWatches(Object oldval, Object newval){
88 IPersistentMap ws = watches;
89 if(ws.count() > 0)
90 {
91 for(ISeq s = ws.seq(); s != null; s = s.next())
92 {
93 Map.Entry e = (Map.Entry) s.first();
94 IFn fn = (IFn) e.getValue();
95 try
96 {
97 if(fn != null)
98 fn.invoke(e.getKey(), this, oldval, newval);
99 }
100 catch(Exception e1)
101 {
102 throw new RuntimeException(e1);
103 }
104 }
105 }
106 }
107 }