public Action <T, OTasks.ParallelLoopState> WrapBody(Action <T> body) { return((T t, OTasks.ParallelLoopState ls) => { Exception exception = null; MChessChess.TraceEvent("body(" + t.ToString() + ")"); MChessChess.LeaveChess(); if (OThreading.Thread.CurrentThread == mainthread) { protectingcontext.Dispose(); } try { body(t); } catch (Exception e) // catch recoverable exception in user code { exception = e; } if (OThreading.Thread.CurrentThread == mainthread) { protectingcontext = _ProtectingThreadContext.Acquire(); } MChessChess.EnterChess(); if (exception != null) { global::System.Diagnostics.Debug.Fail("Not implemented: exceptions in Parallel loops"); throw exception; // once we implement this we'll rethrow and let TPL catch & aggregate it } }); }
// variable-range parallel for loop helper internal static OTasks.ParallelLoopResult?ParallelForHelper( Func <Range> prologue, bool singlethread, string name, global::System.Action <long> body, Helper.SimpleDel <OTasks.ParallelLoopResult?> orig) { return (Helper.SimpleContextExposingWrap( delegate(ClrSyncManager manager, ref IDisposable protectingcontext) { Range range = new Range(); // do prologue outside chess... and switch protecting context MChessChess.LeaveChess(); protectingcontext.Dispose(); Exception ex = null; try { range = prologue(); } catch (Exception e) // catch recoverable exception in user code { ex = e; } IDisposable pc = _ProtectingThreadContext.Acquire(); MChessChess.EnterChess(); if (ex != null) { global::System.Diagnostics.Debug.Fail("Not implemented: exceptions in enumerators of Parallel foreach"); throw ex; } if (range.to <= range.from) // empty loop { return orig(); } long split; if (!singlethread) { split = range.minsplit + manager.Choose((int)(range.maxsplit - range.minsplit + 1)); } else { split = (manager.Choose(2) == 0) ? range.minsplit : range.maxsplit; } MChessChess.TraceEvent(name + "(" + range.from + "," + range.to + "), split " + split); SimplePartitioner <long> partitioner = new SimplePartitioner <long>( manager, range.from, range.to, split, (long i) => { return i; }, true); // store protecting context partitioner.protectingcontext = pc; // TODO better job here OTasks.ParallelOptions options = new OTasks.ParallelOptions(); options.MaxDegreeOfParallelism = 2; OTasks.ParallelLoopResult result = OTasks.Parallel.ForEach <long>(partitioner, options, partitioner.WrapBody(body)); // switch protecting context back partitioner.protectingcontext.Dispose(); protectingcontext = _ProtectingThreadContext.Acquire(); return result; }, orig )); }
public static void TraceEvent(string info) { using (new WrapperSentry()) MChessChess.TraceEvent(info); }