/// <summary> /// Creates a new <see cref="Machine"/> of the specified <see cref="Type"/>. The /// method returns only when the machine is initialized and the <see cref="Event"/> /// (if any) is handled. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="friendlyName">Friendly machine name used for logging</param> /// <param name="e">Event passed during machine construction</param> /// <param name="creator">Creator machine</param> /// <returns>MachineId</returns> internal override async Task <MachineId> CreateMachineAndExecute(Type type, string friendlyName, Event e, Machine creator) { Machine machine = this.CreateMachine(type, friendlyName); await this.RunMachineEventHandlerAsync(machine, e, true); return(machine.Id); }
internal virtual void NotifyDefaultHandlerFired(Machine machine) { // Override to implement the notification. }
/// <summary> /// Creates a new <see cref="Machine"/> of the specified <see cref="Type"/>. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="friendlyName">Friendly machine name used for logging</param> /// <param name="e">Event passed during machine construction</param> /// <param name="creator">Creator machine</param> /// <returns>MachineId</returns> internal override MachineId CreateMachine(Type type, string friendlyName, Event e, Machine creator) { Machine machine = this.CreateMachine(type, friendlyName); this.RunMachineEventHandler(machine, e, true); return(machine.Id); }
internal virtual void NotifyReceivedEvent(Machine machine, EventInfo eventInfo) { // Override to implement the notification. }
internal virtual void NotifyHalted(Machine machine, LinkedList <EventInfo> inbox) { // Override to implement the notification. }
/// <summary> /// Notifies that a machine has halted. /// </summary> /// <param name="machine">Machine</param> internal override void NotifyHalted(Machine machine) { base.Log($"<HaltLog> Machine '{machine.Id}' halted."); this.MachineMap.TryRemove(machine.Id.Value, out machine); }
/// <summary> /// Notifies that a machine received an event that it was waiting for. /// </summary> /// <param name="mid">Machine id</param> internal static void NotifyReceivedEvent(MachineId mid) { Machine machine = PSharpRuntime.MachineMap[mid.Value]; PSharpRuntime.BugFinder.NotifyTaskReceivedEvent(machine); }
internal virtual void NotifyCompletedAction(Machine machine, MethodInfo action, Event receivedEvent) { // Override to implement the notification. }
internal virtual void NotifyPop(Machine machine) { // Override to implement the notification. }
internal virtual bool CheckStartEventHandler(Machine machine) { return(true); }
internal virtual void NotifyExitedState(Machine machine) { // Override to implement the notification. }
/// <summary> /// Creates a new remote <see cref="Machine"/> of the specified <see cref="System.Type"/>. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="friendlyName">Friendly machine name used for logging</param> /// <param name="endpoint">Endpoint</param> /// <param name="operationGroupId">Operation group id</param> /// <param name="e">Event passed during machine construction</param> /// <param name="creator">Creator machine</param> /// <returns>MachineId</returns> internal abstract MachineId CreateRemoteMachine(Type type, string friendlyName, string endpoint, Event e, Machine creator, Guid?operationGroupId);
/// <summary> /// Creates a new <see cref="Machine"/> of the specified <see cref="Type"/>. The /// method returns only when the machine is initialized and the <see cref="Event"/> /// (if any) is handled. /// </summary> /// <param name="mid">Unbound machine id</param> /// <param name="type">Type of the machine</param> /// <param name="friendlyName">Friendly machine name used for logging</param> /// <param name="e">Event passed during machine construction</param> /// <param name="operationGroupId">Operation group id</param> /// <param name="creator">Creator machine</param> /// <returns>MachineId</returns> internal abstract Task <MachineId> CreateMachineAndExecute(MachineId mid, Type type, string friendlyName, Event e, Machine creator, Guid?operationGroupId);
/// <summary> /// Creates a new <see cref="Machine"/> of the specified <see cref="Type"/>. /// </summary> /// <param name="mid">Unbound machine id</param> /// <param name="type">Type of the machine</param> /// <param name="friendlyName">Friendly machine name used for logging</param> /// <param name="operationGroupId">Operation group id</param> /// <param name="e">Event passed during machine construction</param> /// <param name="creator">Creator machine</param> /// <returns>MachineId</returns> internal abstract MachineId CreateMachine(MachineId mid, Type type, string friendlyName, Event e, Machine creator, Guid?operationGroupId);
/// <summary> /// Notifies that a machine dequeued an <see cref="Event"/>. /// </summary> /// <param name="machine">Machine</param> /// <param name="eventInfo">EventInfo</param> internal override void NotifyDequeuedEvent(Machine machine, EventInfo eventInfo) { base.Log($"<DequeueLog> Machine '{machine.Id}' dequeued " + $"event '{eventInfo.EventName}'."); }
internal virtual void NotifyReceiveCalled(Machine machine) { // Override to implement the notification. }
/// <summary> /// Notifies that a machine is waiting to receive one or more events. /// </summary> /// <param name="machine">Machine</param> internal override void NotifyWaitEvents(Machine machine) { base.Log($"<ReceiveLog> Machine '{machine.Id}' is waiting to receive an event."); }
/// <summary> /// Notifies that a machine is waiting to receive one or more events. /// </summary> /// <param name="machine">Machine</param> /// <param name="eventInfoInInbox">The event info if it is in the inbox, else null</param> internal virtual void NotifyWaitEvents(Machine machine, EventInfo eventInfoInInbox) { // Override to implement the notification. }
/// <summary> /// Initializes the state. /// </summary> /// <param name="machine">Machine</param> internal void InitializeState(Machine machine) { this.Machine = machine; this.GotoTransitions = new GotoStateTransitions(); this.PushTransitions = new PushStateTransitions(); this.ActionBindings = new ActionBindings(); this.IgnoredEvents = new HashSet <Type>(); this.DeferredEvents = new HashSet <Type>(); var entryAttribute = this.GetType().GetCustomAttribute(typeof(OnEntry), false) as OnEntry; var exitAttribute = this.GetType().GetCustomAttribute(typeof(OnExit), false) as OnExit; if (entryAttribute != null) { var method = this.Machine.GetType().GetMethod(entryAttribute.Action, BindingFlags.NonPublic | BindingFlags.Instance); var action = (Action)Delegate.CreateDelegate(typeof(Action), this.Machine, method); this.EntryAction = action; } if (exitAttribute != null) { var method = this.Machine.GetType().GetMethod(exitAttribute.Action, BindingFlags.NonPublic | BindingFlags.Instance); var action = (Action)Delegate.CreateDelegate(typeof(Action), this.Machine, method); this.ExitAction = action; } var gotoAttributes = this.GetType().GetCustomAttributes(typeof(OnEventGotoState), false) as OnEventGotoState[]; var pushAttributes = this.GetType().GetCustomAttributes(typeof(OnEventPushState), false) as OnEventPushState[]; var doAttributes = this.GetType().GetCustomAttributes(typeof(OnEventDoAction), false) as OnEventDoAction[]; foreach (var attr in gotoAttributes) { if (attr.Action == null) { this.GotoTransitions.Add(attr.Event, attr.State); } else { var method = this.Machine.GetType().GetMethod(attr.Action, BindingFlags.NonPublic | BindingFlags.Instance); var action = (Action)Delegate.CreateDelegate(typeof(Action), this.Machine, method); this.GotoTransitions.Add(attr.Event, attr.State, action); } } foreach (var attr in pushAttributes) { this.PushTransitions.Add(attr.Event, attr.State); } foreach (var attr in doAttributes) { var method = this.Machine.GetType().GetMethod(attr.Action, BindingFlags.NonPublic | BindingFlags.Instance); var action = (Action)Delegate.CreateDelegate(typeof(Action), this.Machine, method); this.ActionBindings.Add(attr.Event, action); } var ignoreEventsAttribute = this.GetType().GetCustomAttribute(typeof(IgnoreEvents), false) as IgnoreEvents; var deferEventsAttribute = this.GetType().GetCustomAttribute(typeof(DeferEvents), false) as DeferEvents; if (ignoreEventsAttribute != null) { this.IgnoredEvents.UnionWith(ignoreEventsAttribute.Events); } if (deferEventsAttribute != null) { this.DeferredEvents.UnionWith(deferEventsAttribute.Events); } }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> internal static void Send(MachineId mid, Event e) { if (mid == null) { ErrorReporter.ReportAndExit("Cannot send to a null machine."); } else if (e == null) { ErrorReporter.ReportAndExit("Cannot send a null event."); } if (PSharpRuntime.TaskMap.ContainsKey((int)Task.CurrentId)) { Machine sender = PSharpRuntime.TaskMap[(int)Task.CurrentId]; Output.Log("<SendLog> Machine '{0}({1})' sent event '{2}' to '{3}({4})'.", sender, sender.Id.MVal, e.GetType(), mid.Type, mid.MVal); } else { Output.Log("<SendLog> Event '{0}' was sent to '{1}({2})'.", e.GetType(), mid.Type, mid.MVal); } Machine machine = PSharpRuntime.MachineMap[mid.Value]; bool runHandler = false; machine.Enqueue(e, ref runHandler); if (!runHandler) { PSharpRuntime.BugFinder.Schedule(); return; } Task task = new Task(() => { PSharpRuntime.BugFinder.NotifyTaskStarted(); machine.RunEventHandler(); PSharpRuntime.BugFinder.NotifyTaskCompleted(); }); lock (PSharpRuntime.Lock) { PSharpRuntime.MachineTasks.Add(task); PSharpRuntime.TaskMap.Add(task.Id, machine as Machine); } PSharpRuntime.BugFinder.NotifyNewTaskCreated(task.Id, machine); if (PSharpRuntime.Configuration.ScheduleIntraMachineConcurrency) { task.Start(PSharpRuntime.TaskScheduler); } else { task.Start(); } PSharpRuntime.BugFinder.WaitForTaskToStart(task.Id); PSharpRuntime.BugFinder.Schedule(); }