public T OrElse <T>(StmAction <T> p, StmAction <T> q) { TLog fst = this.StartNested(); try { T result = p(fst); fst.Lock(); bool isValid = fst.IsValid(); fst.UnLock(); if (isValid) { fst.MergeNested(); return(result); } else { throw new CommitFailedException(); } } catch (RetryException) { TLog snd = this.StartNested(); try { T result = q(snd); snd.Lock(); bool isValid = snd.IsValid(); snd.UnLock(); if (isValid) { snd.MergeNested(); return(result); } else { throw new CommitFailedException(); } } catch (RetryException) { this.Lock(); bool isValid = fst.IsValidSingle() && snd.IsValidSingle() && this.IsValid(); this.UnLock(); if (isValid) { fst.MergeNested(); snd.MergeNested(); throw; } else { throw new CommitFailedException(); } } catch (CommitFailedException) { throw; } catch (ThreadInterruptedException) { throw; } catch { snd.Lock(); bool isValid = snd.IsValid(); snd.UnLock(); if (isValid) { snd.MergeNested(); throw; } else { throw new CommitFailedException(); } } } catch (CommitFailedException) { throw; } catch (ThreadInterruptedException) { throw; } catch { fst.Lock(); bool isValid = fst.IsValid(); fst.UnLock(); if (isValid) { fst.MergeNested(); throw; } else { throw new CommitFailedException(); } } }
public static T Atomic <T>(StmAction <T> p) { TLog trans = new TLog(); while (true) { bool retry = false; try { T result = p(trans); trans.Lock(); bool isValid = trans.IsValid(); if (isValid) { trans.Commit(); trans.Signal(); } trans.UnLock(); if (isValid) { return(result); } } catch (RetryException) { // cannot receive ThreadInterruptedException in catch handler retry = true; } catch (CommitFailedException) { } catch (ThreadInterruptedException) { throw; } catch { trans.Lock(); bool isValid = trans.IsValid(); trans.UnLock(); if (isValid) { throw; } } if (retry) { trans.Lock(); bool isValid = trans.IsValid(); if (isValid) { trans.Wait(); try { do { trans.Block(); }while (trans.IsValid()); } finally { trans.UnWait(); trans.UnLock(); } } else { trans.UnLock(); } } trans.log.Clear(); Thread.Sleep(0); } }