Release coccinelle-0.1.5
[bpt/coccinelle.git] / commons / ocollection / oassoc_buffer.ml
CommitLineData
34e49164
C
1open Common
2
3open Oassoc
4
5open Oassocb
6open Osetb
7
8(* todo: limit number of entries, and erase all (then better do a ltu)
9 * todo: another cache that behave as in lfs1,
10 * every 100 operation do a flush
11 *
12 * todo: choose between oassocb and oassoch ?
91eba41f
C
13 *
14 * Also take care that must often redefine all function in the original
15 * oassoc.ml because if some methods are not redefined, for instance
16 * #clear, then if do wrapper over a oassocdbm, then even if oassocdbm
17 * redefine #clear, it will not be called, but instead the default
18 * method will be called that internally will call another method.
19 * So better delegate all the methods and override even the method
20 * with a default definition.
21 *
22 * In the same way sometimes an exn can occur at wierd time. When
23 * we add an element, sometimes this may raise an exn such as Out_of_memory,
24 * but as we dont add directly but only at flush time, the exn
25 * may happen far later the user added something in this oassoc.
26 * Also in the case of Out_of_memory, even if the entry is not
27 * added in the wrapped, it will still be present in the cache
28 * and so the next flush will still generate an exn that again
29 * may not be cached. So for the moment if Out_of_memory then
30 * do something special and erase the entry in the cache.
34e49164
C
31 *)
32
33(* !!take care!!: this class has side effect, not a pure oassoc *)
34(* can not make it pure, cos the assoc have side effect on the cache *)
35class ['a,'b] oassoc_buffer max cached =
36object(o)
37 inherit ['a,'b] oassoc
38
39 val counter = ref 0
40 val cache = ref (new oassocb [])
41 val dirty = ref (new osetb Setb.empty)
42 val wrapped = ref cached
43
44 method private myflush =
91eba41f
C
45
46 let has_a_raised = ref false in
47
34e49164 48 !dirty#iter (fun k ->
91eba41f
C
49 try
50 wrapped := !wrapped#add (k, !cache#assoc k)
51 with Out_of_memory ->
52 pr2 "PBBBBBB: Out_of_memory in oassoc_buffer, but still empty cache";
53 has_a_raised := true;
34e49164
C
54 );
55 dirty := (new osetb Setb.empty);
56 cache := (new oassocb []);
57 counter := 0;
91eba41f
C
58 if !has_a_raised then raise Out_of_memory
59
34e49164
C
60
61 method misc_op_hook2 = o#myflush
62
63 method empty =
64 raise Todo
91eba41f
C
65
66 (* what happens in k is already present ? or if add multiple times
67 * the same k ? cache is a oassocb and so the previous binding is
68 * still there, but dirty is a set, and in myflush we iter based
69 * on dirty so we will flush only the last 'k' in the cache.
70 *)
34e49164
C
71 method add (k,v) =
72 cache := !cache#add (k,v);
73 dirty := !dirty#add k;
74 incr counter;
75 if !counter > max then o#myflush;
76 o
77
78 method iter f =
79 o#myflush; (* bugfix: have to flush !!! *)
80 !wrapped#iter f
81
82
91eba41f
C
83 method keys =
84 o#myflush; (* bugfix: have to flush !!! *)
85 !wrapped#keys
86
87 method clear =
88 o#myflush; (* bugfix: have to flush !!! *)
89 !wrapped#clear
90
91
34e49164
C
92 method length =
93 o#myflush;
94 !wrapped#length
95
96 method view =
97 raise Todo
98
99 method del (k,v) =
100 cache := !cache#del (k,v);
101 (* TODO as for delkey, do a try over wrapped *)
102 wrapped := !wrapped#del (k,v);
103 dirty := !dirty#del k;
104 o
105 method mem e = raise Todo
106 method null = raise Todo
107
108 method assoc k =
109 try !cache#assoc k
110 with Not_found ->
111 (* may launch Not_found, but this time, dont catch it *)
112 let v = !wrapped#assoc k in
113 begin
114 cache := !cache#add (k,v);
115 (* otherwise can use too much mem *)
116 incr counter;
117 if !counter > max then o#myflush;
118 v
119 end
120
121 method delkey k =
122 cache := !cache#delkey k;
123 (* sometimes have not yet flushed, so may not be yet in, (could
124 * also flush in place of doing try).
125 *
126 * TODO would be better to see if was in cache (in case mean that
127 * perhaps not flushed and do try and in other case just cos del
128 * (without try) cos forcement flushed ou was an error *)
129 begin
130 try wrapped := !wrapped#delkey k
131 with Not_found -> ()
132 end;
133 dirty := !dirty#del k;
134 o
135
136end
137
138
139(*
140class ['a,'b] oassoc_cache cache cached max =
141 object(o)
142 inherit ['a,'b] oassoc
143
144 val full = ref 0
145 val max = max
146 val cache = cache
147 val cached = cached
148 val lru = TODO
149
150 val data = Hashtbl.create 100
151
152 method empty = raise Todo
153 method add (k,v) = (Hashtbl.add data k v; o)
154 method iter f = cached#iter f
155 method view = raise Todo
156
157 method del (k,v) = (cache#del (k,v); cached#del (k,v); o)
158 method mem e = raise Todo
159 method null = raise Todo
160
161 method assoc k = Hashtbl.find data k
162 method delkey k = (cache#delkey (k,v); cached#del (k,v); o)
163end
164*)
165
166