(Callable fn)
| 254 | } |
| 255 | |
| 256 | Object run(Callable fn) throws Exception{ |
| 257 | boolean done = false; |
| 258 | Object ret = null; |
| 259 | ArrayList<Ref> locked = new ArrayList<Ref>(); |
| 260 | ArrayList<Notify> notify = new ArrayList<Notify>(); |
| 261 | |
| 262 | for(int i = 0; !done && i < RETRY_LIMIT; i++) |
| 263 | { |
| 264 | try |
| 265 | { |
| 266 | getReadPoint(); |
| 267 | if(i == 0) |
| 268 | { |
| 269 | startPoint = readPoint; |
| 270 | startTime = System.nanoTime(); |
| 271 | } |
| 272 | info = new Info(RUNNING, startPoint); |
| 273 | ret = fn.call(); |
| 274 | //make sure no one has killed us before this point, and can't from now on |
| 275 | if(info.status.compareAndSet(RUNNING, COMMITTING)) |
| 276 | { |
| 277 | for(Map.Entry<Ref, ArrayList<CFn>> e : commutes.entrySet()) |
| 278 | { |
| 279 | Ref ref = e.getKey(); |
| 280 | if(sets.contains(ref)) continue; |
| 281 | |
| 282 | boolean wasEnsured = ensures.contains(ref); |
| 283 | //can't upgrade readLock, so release it |
| 284 | releaseIfEnsured(ref); |
| 285 | tryWriteLock(ref); |
| 286 | locked.add(ref); |
| 287 | if(wasEnsured && ref.tvals != null && ref.tvals.point > readPoint) |
| 288 | throw retryex; |
| 289 | |
| 290 | Info refinfo = ref.tinfo; |
| 291 | if(refinfo != null && refinfo != info && refinfo.running()) |
| 292 | { |
| 293 | if(!barge(refinfo)) |
| 294 | throw retryex; |
| 295 | } |
| 296 | Object val = ref.tvals == null ? null : ref.tvals.val; |
| 297 | vals.put(ref, val); |
| 298 | for(CFn f : e.getValue()) |
| 299 | { |
| 300 | vals.put(ref, f.fn.applyTo(RT.cons(vals.get(ref), f.args))); |
| 301 | } |
| 302 | } |
| 303 | for(Ref ref : sets) |
| 304 | { |
| 305 | tryWriteLock(ref); |
| 306 | locked.add(ref); |
| 307 | } |
| 308 | |
| 309 | //validate and enqueue notifications |
| 310 | for(Map.Entry<Ref, Object> e : vals.entrySet()) |
| 311 | { |
| 312 | Ref ref = e.getKey(); |
| 313 | ref.validate(ref.getValidator(), e.getValue()); |
no test coverage detected