/// <summary> /// Initializes this monitor. /// </summary> /// <param name="mid">MachineId</param> internal void Initialize(MachineId mid) { this.Id = mid; this.Runtime = mid.Runtime; this.IsInsideOnExit = false; this.CurrentActionCalledTransitionStatement = false; }
/// <summary> /// Creates a new machine id. /// </summary> /// <param name="type">Machine type</param> /// <param name="friendlyName">Friendly machine name</param> /// <param name="runtime">PSharpRuntime</param> /// <param name="useNameForHashing">Use friendly name as the id</param> internal MachineId(Type type, string friendlyName, PSharpRuntime runtime, bool useNameForHashing = false) { Runtime = runtime; Endpoint = Runtime.NetworkProvider.GetLocalEndpoint(); if (useNameForHashing) { Value = 0; NameValue = friendlyName; Runtime.Assert(!string.IsNullOrEmpty(NameValue), "Input friendlyName cannot be null when used as Id"); } else { // Atomically increments and safely wraps into an unsigned long. Value = (ulong)Interlocked.Increment(ref runtime.MachineIdCounter) - 1; NameValue = string.Empty; // Checks for overflow. Runtime.Assert(Value != ulong.MaxValue, "Detected MachineId overflow."); } Generation = runtime.Configuration.RuntimeGeneration; Type = type.FullName; if (IsNameUsedForHashing) { Name = NameValue; } else { Name = string.Format("{0}({1})", string.IsNullOrEmpty(friendlyName) ? Type : friendlyName, Value); } }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="target">Target machine id</param> /// <param name="e">Event</param> /// <param name="payload">Optional payload</param> public static void SendEvent(MachineId target, Event e, params Object[] payload) { // If the event is null then report an error and exit. PSharpRuntime.Assert(e != null, "Cannot send a null event."); e.AssignPayload(payload); PSharpRuntime.Send(target, e); }
/// <summary> /// Invokes the specified monitor with the given event. /// </summary> /// <typeparam name="T">Type of the monitor</typeparam> /// <param name="e">Event</param> /// <param name="payload">Optional payload</param> public static void InvokeMonitor <T>(Event e, params Object[] payload) { // If the event is null then report an error and exit. PSharpRuntime.Assert(e != null, "Cannot send a null event."); e.AssignPayload(payload); PSharpRuntime.Monitor <T>(e); }
/// <summary> /// Notifies that a scheduling point should be instrumented /// due to a wait synchronization operation. /// </summary> /// <param name="blockingTasks">Blocking tasks</param> /// <param name="waitAll">Boolean value</param> internal static void ScheduleOnWait(IEnumerable <Task> blockingTasks, bool waitAll) { PSharpRuntime.Assert(PSharpRuntime.BugFinder is TaskAwareBugFindingScheduler, "Cannot schedule on wait without enabling the task-aware bug finding scheduler."); (PSharpRuntime.BugFinder as TaskAwareBugFindingScheduler).NotifyTaskBlocked( Task.CurrentId, blockingTasks, waitAll); PSharpRuntime.BugFinder.Schedule(); }
/// <summary> /// Blocks and waits to receive an event of the given types, and /// executes a given action on receiving the event. Returns a /// payload, if there is any, else returns null. /// </summary> /// <returns>Payload</returns> public static Object Receive(params Tuple <Type, Action>[] events) { PSharpRuntime.Assert(Task.CurrentId != null, "Only machines can wait to receive an event."); PSharpRuntime.Assert(PSharpRuntime.TaskMap.ContainsKey((int)Task.CurrentId), "Only machines can wait to receive an event; task {0} does not belong to a machine.", (int)Task.CurrentId); Machine machine = PSharpRuntime.TaskMap[(int)Task.CurrentId]; machine.Receive(events); return(machine.Payload); }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> void IDispatcher.Send(MachineId mid, Event e) { if (mid.IpAddress.Length > 0) { PSharpRuntime.SendRemotely(mid, e); } else { PSharpRuntime.Send(mid, e); } }
/// <summary> /// Creates a new machine of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> /// <returns>Machine id</returns> public static MachineId CreateMachine(Type type, params Object[] payload) { lock (PSharpRuntime.Lock) { if (!PSharpRuntime.IsRunning) { PSharpRuntime.Initialize(); } } return(PSharpRuntime.TryCreateMachine(type, payload)); }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="target">Target machine id</param> /// <param name="e">Event</param> /// <param name="payload">Optional payload</param> public static void SendEvent(MachineId target, Event e, params Object[] payload) { e.AssignPayload(payload); try { PSharpRuntime.Send(target, e); } catch (TaskCanceledException) { Output.Log("<Exception> TaskCanceledException was thrown."); } }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="target">Target machine id</param> /// <param name="e">Event</param> /// <param name="payload">Optional payload</param> public static void SendEvent(MachineId target, Event e, params Object[] payload) { // If the event is null then report an error and exit. PSharpRuntime.Assert(e != null, "Cannot send a null event."); e.AssignPayload(payload); try { PSharpRuntime.Send(target, e); } catch (TaskCanceledException) { Output.Debug("<Exception> TaskCanceledException was thrown."); } }
/// <summary> /// Tries to create a new monitor of the given type with an optional payload. /// </summary> /// <param name="type">Type of the monitor</param> /// <param name="payload">Optional payload</param> internal static void TryCreateMonitor(Type type, params Object[] payload) { PSharpRuntime.Assert(type.IsSubclassOf(typeof(Monitor)), "Type '{0}' is not a " + "subclass of Monitor.\n", type.Name); Object monitor = Activator.CreateInstance(type); Output.Debug(DebugType.Runtime, "<CreateLog> Monitor {0} is created.", type.Name); PSharpRuntime.Monitors.Add(monitor as Monitor); if (Configuration.CheckLiveness) { PSharpRuntime.LivenessChecker.RegisterMonitor(monitor as Monitor); } (monitor as Monitor).AssignInitialPayload(payload); (monitor as Monitor).GotoStartState(); }
/// <summary> /// Constructor. /// </summary> /// <param name="type">Machine type</param> /// <param name="friendlyName">Friendly machine name</param> /// <param name="runtime">PSharpRuntime</param> internal MachineId(Type type, string friendlyName, PSharpRuntime runtime) { this.FriendlyName = friendlyName; this.Runtime = runtime; this.Type = type.FullName; this.EndPoint = this.Runtime.NetworkProvider.GetLocalEndPoint(); this.Value = Interlocked.Increment(ref IdCounter); if (this.FriendlyName != null && this.FriendlyName.Length > 0) { this.Name = string.Format("{0}({1})", this.FriendlyName, this.Value); } else { this.Name = string.Format("{0}({1})", this.Type, this.Value); } }
/// <summary> /// Creates a new machine id. /// </summary> /// <param name="type">Machine type string</param> /// <param name="friendlyName">Friendly machine name</param> /// <param name="runtime">PSharpRuntime</param> internal MachineId(string type, string friendlyName, PSharpRuntime runtime) { Type = type; Runtime = runtime; if (this.Runtime.IsTest()) { this.Value = runtime.GenerateTestId(); // Checks for overflow. Runtime.Assert(Value != ulong.MaxValue, "Detected MachineId overflow."); } if (string.IsNullOrWhiteSpace(friendlyName)) { friendlyName = Runtime.GetFriendlyName(Type); } FriendlyName = friendlyName; Endpoint = Runtime.NetworkProvider.GetLocalEndpoint(); Name = $"({Type})-{FriendlyName}"; }
/// <summary> /// Create a fresh MachineId borrowing information from a given id. /// </summary> /// <param name="mid">MachineId</param> internal MachineId(MachineId mid) { Runtime = mid.Runtime; Endpoint = mid.Endpoint; // Atomically increments and safely wraps into an unsigned long. Value = (ulong)Interlocked.Increment(ref Runtime.MachineIdCounter) - 1; // Checks for overflow. Runtime.Assert(Value != ulong.MaxValue, "Detected MachineId overflow."); Generation = mid.Generation; Type = mid.Type; if (FriendlyName != null && FriendlyName.Length > 0) { Name = string.Format("{0}({1})", FriendlyName, Value); } else { Name = string.Format("{0}({1})", Type, Value); } }
/// <summary> /// Constructor. /// </summary> /// <param name="type">Machine type</param> /// <param name="friendlyName">Friendly machine name</param> /// <param name="runtime">PSharpRuntime</param> internal MachineId(Type type, string friendlyName, PSharpRuntime runtime) { this.FriendlyName = friendlyName; this.Runtime = runtime; this.Type = type.FullName; this.Endpoint = this.Runtime.NetworkProvider.GetLocalEndpoint(); // Atomically increments and safely wraps into an unsigned long. this.Value = (uint)Interlocked.Increment(ref runtime.MachineIdCounter); // Checks for overflow. Runtime.Assert(this.Value != ulong.MaxValue, "Detected MachineId overflow."); if (this.FriendlyName != null && this.FriendlyName.Length > 0) { this.Name = string.Format("{0}({1})", this.FriendlyName, this.Value); } else { this.Name = string.Format("{0}({1})", this.Type, this.Value); } }
/// <summary> /// Creates a new machine id. /// </summary> /// <param name="type">Machine type</param> /// <param name="friendlyName">Friendly machine name</param> /// <param name="runtime">PSharpRuntime</param> internal MachineId(Type type, string friendlyName, PSharpRuntime runtime) { FriendlyName = friendlyName; Runtime = runtime; Endpoint = Runtime.NetworkProvider.GetLocalEndpoint(); // Atomically increments and safely wraps into an unsigned long. Value = (ulong)Interlocked.Increment(ref runtime.MachineIdCounter) - 1; // Checks for overflow. Runtime.Assert(Value != ulong.MaxValue, "Detected MachineId overflow."); Generation = runtime.Configuration.RuntimeGeneration; Type = type.FullName; if (friendlyName != null && friendlyName.Length > 0) { Name = string.Format("{0}({1})", friendlyName, Value); } else { Name = string.Format("{0}({1})", Type, Value); } }
/// <summary> /// Tries to create a new task machine. /// </summary> /// <param name="userTask">Task</param> internal static void TryCreateTaskMachine(Task userTask) { PSharpRuntime.Assert(PSharpRuntime.TaskScheduler is TaskWrapperScheduler, "Unable to wrap " + "the task in a machine, because the task wrapper scheduler is not enabled.\n"); TaskMachine taskMachine = new TaskMachine(PSharpRuntime.TaskScheduler as TaskWrapperScheduler, userTask); MachineId mid = taskMachine.Id; Output.Log("<CreateLog> TaskMachine({0}) is created.", mid.MVal); Task task = new Task(() => { PSharpRuntime.BugFinder.NotifyTaskStarted(); taskMachine.Run(); PSharpRuntime.BugFinder.NotifyTaskCompleted(); }); lock (PSharpRuntime.Lock) { PSharpRuntime.MachineTasks.Add(task); } PSharpRuntime.BugFinder.NotifyNewTaskCreated(task.Id, taskMachine); if (PSharpRuntime.Configuration.ScheduleIntraMachineConcurrency) { task.Start(PSharpRuntime.TaskScheduler); } else { task.Start(); } PSharpRuntime.BugFinder.WaitForTaskToStart(task.Id); PSharpRuntime.BugFinder.Schedule(); }
/// <summary> /// Tries to create a new monitor of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> void IDispatcher.TryCreateMonitor(Type type, params Object[] payload) { PSharpRuntime.TryCreateMonitor(type, payload); }
/// <summary> /// Tries to create a new remote machine of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> /// <returns>Machine id</returns> MachineId IDispatcher.TryCreateRemoteMachine(Type type, params Object[] payload) { // Remote does not work in the bug-finding runtime. return(PSharpRuntime.TryCreateMachine(type, payload)); }
/// <summary> /// Tries to create a new machine of the given type with an optional payload. /// </summary> /// <param name="type">Type of the machine</param> /// <param name="payload">Optional payload</param> /// <returns>Machine id</returns> MachineId IDispatcher.TryCreateMachine(Type type, params Object[] payload) { return(PSharpRuntime.TryCreateMachine(type, payload)); }
/// <summary> /// Notifies that a scheduling point should be instrumented /// due to a wait synchronization operation. /// </summary> /// <param name="blockingTasks">Blocking tasks</param> /// <param name="waitAll">Boolean value</param> void IDispatcher.ScheduleOnWait(IEnumerable <Task> blockingTasks, bool waitAll) { PSharpRuntime.ScheduleOnWait(blockingTasks, waitAll); }
/// <summary> /// Notifies that a default handler has been used. /// </summary> void IDispatcher.NotifyDefaultHandlerFired() { PSharpRuntime.NotifyDefaultHandlerFired(); }
/// <summary> /// Invokes the specified monitor with the given event. /// </summary> /// <typeparam name="T">Type of the monitor</typeparam> /// <param name="e">Event</param> void IDispatcher.Monitor <T>(Event e) { PSharpRuntime.Monitor <T>(e); }
/// <summary> /// Checks if the assertion holds, and if not it reports /// an error and exits. /// </summary> /// <param name="predicate">Predicate</param> /// <param name="s">Message</param> /// <param name="args">Message arguments</param> void IDispatcher.Assert(bool predicate, string s, params object[] args) { PSharpRuntime.Assert(predicate, s, args); }
/// <summary> /// Checks if the assertion holds, and if not it reports /// an error and exits. /// </summary> /// <param name="predicate">Predicate</param> void IDispatcher.Assert(bool predicate) { PSharpRuntime.Assert(predicate); }
/// <summary> /// Tries to create a new task machine. /// </summary> /// <param name="userTask">Task</param> void IDispatcher.TryCreateTaskMachine(Task userTask) { PSharpRuntime.TryCreateTaskMachine(userTask); }
/// <summary> /// Sends an asynchronous event to a machine. /// </summary> /// <param name="mid">Machine id</param> /// <param name="e">Event</param> void IDispatcher.Send(MachineId mid, Event e) { PSharpRuntime.Send(mid, e); }
/// <summary> /// Notifies that a machine is waiting to receive an event. /// </summary> /// <param name="mid">Machine id</param> void IDispatcher.NotifyWaitEvent(MachineId mid) { PSharpRuntime.NotifyWaitEvent(); }
/// <summary> /// Returns a nondeterministic boolean choice, that can be /// controlled during analysis or testing. /// </summary> /// <returns>Boolean</returns> bool IDispatcher.Nondet() { return(PSharpRuntime.Nondet()); }
/// <summary> /// Notifies that a machine received an event that it was waiting for. /// </summary> /// <param name="mid">Machine id</param> void IDispatcher.NotifyReceivedEvent(MachineId mid) { PSharpRuntime.NotifyReceivedEvent(mid); }