public void Send(T msg) { runtime.Schedule(OpType.SEND); LogSend(msg); mailbox.Add(msg); if (waiter != null) { Safety.Assert(!waiter.enabled); waiter.enabled = true; waiter = null; } }
public static T ActorBody <T>( Func <T> func, TestingActorRuntime runtime, bool mainThread, ActorInfo info = null) { if (info == null) { info = runtime.GetCurrentActorInfo(); } lock (info.mutex) { Safety.Assert(info.active); info.currentOp = OpType.START; if (!mainThread) { info.active = false; Monitor.PulseAll(info.mutex); while (!info.active) { Monitor.Wait(info.mutex); } } } try { return(func()); } catch (OperationCanceledException ex) { lock (info.mutex) { if (info.cts.Token == ex.CancellationToken && info.cts.IsCancellationRequested) { info.cancelled = true; } info.exceptions.Add(ex); } throw; } catch (ActorTerminatedException ex) { if (mainThread && runtime.error == null) { runtime.error = new Exception("Main actor did not terminate.", ex); } } catch (Exception ex) { runtime.error = ex; runtime.terminated = true; runtime.ActivateAllActors(); } finally { try { if (!runtime.terminated) { runtime.Schedule(OpType.END, info); lock (info.mutex) { info.enabled = false; info.terminated = true; foreach (var waiter in info.terminateWaiters) { waiter.enabled = true; } info.terminateWaiters.Clear(); } runtime.Schedule(OpType.END, info); } } catch (ActorTerminatedException) { } finally { lock (info.mutex) { info.terminated = true; } } } return(default(T)); }