Esempio n. 1
0
        /// <summary>
        /// Sends an asynchronous <see cref="Event"/> to a machine and
        /// executes the event handler if the machine is available.
        /// </summary>
        /// <param name="mid">MachineId</param>
        /// <param name="e">Event</param>
        /// <param name="sender">Sender machine</param>
        internal override async Task SendEventAndExecute(MachineId mid, Event e, AbstractMachine sender)
        {
            Machine machine = null;

            if (!this.MachineMap.TryGetValue(mid.Value, out machine))
            {
                if (sender != null)
                {
                    base.Log($"<SendLog> Machine '{sender.Id}' sent event '{e.GetType().FullName}' to a halted machine '{mid}'.");
                }
                else
                {
                    base.Log($"<SendLog> The event '{e.GetType().FullName}' was sent to a halted machine '{mid}'.");
                }

                return;
            }

            bool runNewHandler = false;

            this.EnqueueEvent(machine, e, sender, ref runNewHandler);
            if (runNewHandler)
            {
                await this.RunMachineEventHandlerAsync(machine, null, false);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Returns a nondeterministic integer choice, that can be
        /// controlled during analysis or testing.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="maxValue">Max value</param>
        /// <returns>Integer</returns>
        internal virtual int GetNondeterministicIntegerChoice(
            AbstractMachine machine, int maxValue)
        {
            Random random = new Random(DateTime.Now.Millisecond);

            return(random.Next(maxValue));
        }
Esempio n. 3
0
        /// <summary>
        /// Notifies that a machine exited a state.
        /// </summary>
        /// <param name="machine">AbstractMachine</param>
        internal override void NotifyExitedState(AbstractMachine machine)
        {
            if (base.Configuration.Verbose <= 1)
            {
                return;
            }

            if (machine is Machine)
            {
                string machineState = (machine as Machine).CurrentStateName;

                base.Log($"<StateLog> Machine '{machine.Id}' exits " +
                         $"state '{machineState}'.");
            }
            else if (machine is Monitor)
            {
                string liveness     = "";
                string monitorState = (machine as Monitor).CurrentStateName;

                if ((machine as Monitor).IsInHotState())
                {
                    liveness      = "'hot' ";
                    monitorState += "[hot]";
                }
                else if ((machine as Monitor).IsInColdState())
                {
                    liveness      = "'cold' ";
                    monitorState += "[cold]";
                }

                base.Log($"<MonitorLog> Monitor '{machine.GetType().Name}' " +
                         $"exits {liveness}state '{monitorState}'.");
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Invokes the specified <see cref="PSharp.Monitor"/> with the specified <see cref="Event"/>.
        /// </summary>
        /// <param name="sender">Sender machine</param>
        /// <param name="type">Type of the monitor</param>
        /// <param name="e">Event</param>
        internal override void Monitor(Type type, AbstractMachine sender, Event e)
        {
            if (!base.Configuration.EnableMonitorsInProduction)
            {
                // No-op in production.
                return;
            }

            Monitor monitor = null;

            lock (this.Monitors)
            {
                foreach (var m in this.Monitors)
                {
                    if (m.GetType() == type)
                    {
                        monitor = m;
                        break;
                    }
                }
            }

            if (monitor != null)
            {
                lock (monitor)
                {
                    monitor.MonitorEvent(e);
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Returns a nondeterministic integer choice, that can be
        /// controlled during analysis or testing.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="maxValue">Max value</param>
        /// <returns>Integer</returns>
        internal override int GetNondeterministicIntegerChoice(AbstractMachine machine, int maxValue)
        {
            Random random = new Random(DateTime.Now.Millisecond);
            var    result = random.Next(maxValue);

            base.Logger.OnRandom(machine?.Id, result);

            return(result);
        }
Esempio n. 6
0
        /// <summary>
        /// Sends an asynchronous event to a machine.
        /// </summary>
        /// <param name="sender">Sender machine</param>
        /// <param name="mid">MachineId</param>
        /// <param name="e">Event</param>
        /// <param name="isStarter">Is starting a new operation</param>
        internal virtual void Send(AbstractMachine sender, MachineId mid, Event e, bool isStarter)
        {
            EventOriginInfo originInfo = null;

            if (sender != null && sender is Machine)
            {
                originInfo = new EventOriginInfo(sender.Id,
                                                 (sender as Machine).GetType().Name,
                                                 Machine.GetQualifiedStateName((sender as Machine).CurrentState));
            }

            EventInfo eventInfo = new EventInfo(e, originInfo);

            Machine machine = null;

            if (!this.MachineMap.TryGetValue(mid.Value, out machine))
            {
                return;
            }

            bool runHandler = false;

            machine.Enqueue(eventInfo, ref runHandler);

            if (!runHandler)
            {
                return;
            }

            Task task = new Task(() =>
            {
                try
                {
                    machine.RunEventHandler();
                }
                catch (Exception)
                {
                    if (this.Configuration.ThrowInternalExceptions)
                    {
                        throw;
                    }
                }
                finally
                {
                    this.TaskMap.TryRemove(Task.CurrentId.Value, out machine);
                }
            });

            this.MachineTasks.Add(task);
            this.TaskMap.TryAdd(task.Id, machine);

            task.Start();
        }
Esempio n. 7
0
        /// <summary>
        /// Enqueues an asynchronous <see cref="Event"/> to a machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="e">Event</param>
        /// <param name="sender">Sender machine</param>
        /// <param name="operationGroupId">Operation group id</param>
        /// <param name="runNewHandler">Run a new handler</param>
        private void EnqueueEvent(Machine machine, Event e, AbstractMachine sender, Guid operationGroupId, ref bool runNewHandler)
        {
            EventInfo eventInfo = new EventInfo(e, null);

            eventInfo.SetOperationGroupId(operationGroupId);

            var senderState = (sender as Machine)?.CurrentStateName ?? string.Empty;

            base.Logger.OnSend(machine.Id, sender?.Id, senderState,
                               e.GetType().FullName, operationGroupId, isTargetHalted: false);

            machine.Enqueue(eventInfo, ref runNewHandler);
        }
Esempio n. 8
0
        /// <summary>
        /// Gets the target machine for an event; if not found, logs a halted-machine entry.
        /// </summary>
        /// <param name="targetMachineId">The id of target machine.</param>
        /// <param name="e">The event that will be sent.</param>
        /// <param name="sender">The machine that is sending the event.</param>
        /// <param name="operationGroupId">The operation group id.</param>
        /// <param name="targetMachine">Receives the target machine, if found.</param>
        protected bool GetTargetMachine(MachineId targetMachineId, Event e, AbstractMachine sender,
                                        Guid operationGroupId, out Machine targetMachine)
        {
            if (!this.MachineMap.TryGetValue(targetMachineId, out targetMachine))
            {
                var senderState = (sender as Machine)?.CurrentStateName ?? string.Empty;
                this.Logger.OnSend(targetMachineId, sender?.Id, senderState,
                                   e.GetType().FullName, operationGroupId, isTargetHalted: true);
                return(false);
            }

            return(true);
        }
Esempio n. 9
0
        /// <summary>
        /// Returns a nondeterministic boolean choice, that can be
        /// controlled during analysis or testing.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="maxValue">Max value</param>
        /// <returns>Boolean</returns>
        internal virtual bool GetNondeterministicBooleanChoice(
            AbstractMachine machine, int maxValue)
        {
            Random random = new Random(DateTime.Now.Millisecond);

            bool result = false;

            if (random.Next(maxValue) == 0)
            {
                result = true;
            }

            return(result);
        }
Esempio n. 10
0
        /// <summary>
        /// Returns a nondeterministic boolean choice, that can be
        /// controlled during analysis or testing.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="maxValue">Max value</param>
        /// <returns>Boolean</returns>
        internal override bool GetNondeterministicBooleanChoice(AbstractMachine machine, int maxValue)
        {
            Random random = new Random(DateTime.Now.Millisecond);

            bool result = false;

            if (random.Next(maxValue) == 0)
            {
                result = true;
            }

            base.Logger.OnRandom(machine?.Id, result);

            return(result);
        }
Esempio n. 11
0
 /// <summary>
 /// Sets the operation group id for the specified machine.
 /// </summary>
 /// <param name="created">Machine created</param>
 /// <param name="sender">Sender machine</param>
 /// <param name="operationGroupId">Operation group id</param>
 internal void SetOperationGroupIdForMachine(Machine created, AbstractMachine sender, Guid?operationGroupId)
 {
     if (operationGroupId.HasValue)
     {
         created.Info.OperationGroupId = operationGroupId.Value;
     }
     else if (sender != null)
     {
         created.Info.OperationGroupId = sender.Info.OperationGroupId;
     }
     else
     {
         created.Info.OperationGroupId = Guid.Empty;
     }
 }
Esempio n. 12
0
 /// <summary>
 /// Gets the new operation group id to propagate.
 /// </summary>
 /// <param name="sender">Sender machine</param>
 /// <param name="operationGroupId">Operation group id</param>
 /// <returns>Operation group Id</returns>
 internal Guid GetNewOperationGroupId(AbstractMachine sender, Guid?operationGroupId)
 {
     if (operationGroupId.HasValue)
     {
         return(operationGroupId.Value);
     }
     else if (sender != null)
     {
         return(sender.Info.OperationGroupId);
     }
     else
     {
         return(Guid.Empty);
     }
 }
Esempio n. 13
0
        /// <summary>
        /// Enqueues an asynchronous <see cref="Event"/> to a machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="e">Event</param>
        /// <param name="sender">Sender machine</param>
        /// <param name="runNewHandler">Run a new handler</param>
        private void EnqueueEvent(Machine machine, Event e, AbstractMachine sender, ref bool runNewHandler)
        {
            EventInfo eventInfo = new EventInfo(e, null);

            if (sender != null)
            {
                base.Log($"<SendLog> Machine '{sender.Id}' sent event '{eventInfo.EventName}' to '{machine.Id}'.");
            }
            else
            {
                base.Log($"<SendLog> Event '{eventInfo.EventName}' was sent to '{machine.Id}'.");
            }

            machine.Enqueue(eventInfo, ref runNewHandler);
        }
Esempio n. 14
0
        /// <summary>
        /// Sends an asynchronous <see cref="Event"/> to a machine.
        /// </summary>
        /// <param name="mid">MachineId</param>
        /// <param name="e">Event</param>
        /// <param name="sender">Sender machine</param>
        /// <param name="options">Optional parameters of a send operation.</param>
        internal override void SendEvent(MachineId mid, Event e, AbstractMachine sender, SendOptions options)
        {
            var operationGroupId = base.GetNewOperationGroupId(sender, options?.OperationGroupId);

            if (!base.GetTargetMachine(mid, e, sender, operationGroupId, out Machine machine))
            {
                return;
            }

            bool runNewHandler = false;

            this.EnqueueEvent(machine, e, sender, operationGroupId, ref runNewHandler);
            if (runNewHandler)
            {
                this.RunMachineEventHandler(machine, null, false);
            }
        }
Esempio n. 15
0
        /// <summary>
        /// Returns a nondeterministic integer choice, that can be
        /// controlled during analysis or testing.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="maxValue">Max value</param>
        /// <returns>Integer</returns>
        internal override int GetNondeterministicIntegerChoice(AbstractMachine machine, int maxValue)
        {
            Random random = new Random(DateTime.Now.Millisecond);
            var    result = random.Next(maxValue);

            if (machine != null)
            {
                base.Log($"<RandomLog> Machine '{machine.Id}' " +
                         $"nondeterministically chose '{result}'.");
            }
            else
            {
                base.Log($"<RandomLog> Runtime nondeterministically chose '{result}'.");
            }

            return(result);
        }
Esempio n. 16
0
        /// <summary>
        /// Determines whether the specified System.Object is equal
        /// to the current System.Object.
        /// </summary>
        /// <param name="obj">Object</param>
        /// <returns>Boolean</returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }

            AbstractMachine m = obj as AbstractMachine;

            if (m == null ||
                this.GetType() != m.GetType())
            {
                return(false);
            }

            return(this.Id.Value == m.Id.Value);
        }
Esempio n. 17
0
        /// <summary>
        /// Sends an asynchronous <see cref="Event"/> to a machine and
        /// executes the event handler if the machine is available.
        /// </summary>
        /// <param name="mid">MachineId</param>
        /// <param name="e">Event</param>
        /// <param name="sender">Sender machine</param>
        /// <param name="isStarter">Is starting a new operation</param>
        internal override async Task SendEventAndExecute(MachineId mid, Event e, AbstractMachine sender, bool isStarter)
        {
            Machine machine = null;

            if (!this.MachineMap.TryGetValue(mid.Value, out machine))
            {
                return;
            }

            bool runNewHandler = false;

            this.EnqueueEvent(machine, e, sender, ref runNewHandler);
            if (runNewHandler)
            {
                await this.RunMachineEventHandlerAsync(machine, null, false);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Notifies that a machine raised an <see cref="Event"/>.
        /// </summary>
        /// <param name="machine">AbstractMachine</param>
        /// <param name="eventInfo">EventInfo</param>
        /// <param name="isStarter">Is starting a new operation</param>
        internal override void NotifyRaisedEvent(AbstractMachine machine, EventInfo eventInfo, bool isStarter)
        {
            if (base.Configuration.Verbose <= 1)
            {
                return;
            }

            if (machine is Machine)
            {
                string machineState = (machine as Machine).CurrentStateName;
                base.Log($"<RaiseLog> Machine '{machine.Id}' raised " +
                         $"event '{eventInfo.EventName}'.");
            }
            else if (machine is Monitor)
            {
                string monitorState = (machine as Monitor).CurrentStateName;

                base.Log($"<MonitorLog> Monitor '{machine.GetType().Name}' raised " +
                         $"event '{eventInfo.EventName}'.");
            }
        }
Esempio n. 19
0
        /// <summary>
        /// Notifies that a machine invoked an action.
        /// </summary>
        /// <param name="machine">AbstractMachine</param>
        /// <param name="action">Action</param>
        /// <param name="receivedEvent">Event</param>
        internal override void NotifyInvokedAction(AbstractMachine machine, MethodInfo action, Event receivedEvent)
        {
            if (base.Configuration.Verbose <= 1)
            {
                return;
            }

            if (machine is Machine)
            {
                string machineState = (machine as Machine).CurrentStateName;

                base.Log($"<ActionLog> Machine '{machine.Id}' invoked action " +
                         $"'{action.Name}' in state '{machineState}'.");
            }
            else if (machine is Monitor)
            {
                string monitorState = (machine as Monitor).CurrentStateName;

                base.Log($"<MonitorLog> Monitor '{machine.GetType().Name}' executed " +
                         $"action '{action.Name}' in state '{monitorState}'.");
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Returns a nondeterministic boolean choice, that can be
        /// controlled during analysis or testing.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="maxValue">Max value</param>
        /// <returns>Boolean</returns>
        internal override bool GetNondeterministicBooleanChoice(AbstractMachine machine, int maxValue)
        {
            Random random = new Random(DateTime.Now.Millisecond);

            bool result = false;

            if (random.Next(maxValue) == 0)
            {
                result = true;
            }

            if (machine != null)
            {
                base.Log($"<RandomLog> Machine '{machine.Id}' " +
                         $"nondeterministically chose '{result}'.");
            }
            else
            {
                base.Log($"<RandomLog> Runtime nondeterministically chose '{result}'.");
            }

            return(result);
        }
Esempio n. 21
0
 /// <summary>
 /// Notifies that a machine called Receive.
 /// </summary>
 /// <param name="machine">AbstractMachine</param>
 internal virtual void NotifyReceiveCalled(AbstractMachine machine)
 {
     // No-op for real execution.
 }
Esempio n. 22
0
 /// <summary>
 /// Notifies that a machine raised an event.
 /// </summary>
 /// <param name="machine">AbstractMachine</param>
 /// <param name="eventInfo">EventInfo</param>
 /// <param name="isStarter">Is starting a new operation</param>
 internal virtual void NotifyRaisedEvent(AbstractMachine machine, EventInfo eventInfo, bool isStarter)
 {
     // No-op for real execution.
 }
Esempio n. 23
0
 /// <summary>
 /// Notifies that a machine called Pop.
 /// </summary>
 /// <param name="machine">AbstractMachine</param>
 internal virtual void NotifyPop(AbstractMachine machine)
 {
     // No-op for real execution.
 }
Esempio n. 24
0
 /// <summary>
 /// Notifies that a machine invoked an action.
 /// </summary>
 /// <param name="machine">AbstractMachine</param>
 /// <param name="action">Action</param>
 /// <param name="receivedEvent">Event</param>
 internal virtual void NotifyInvokedAction(AbstractMachine machine, MethodInfo action, Event receivedEvent)
 {
     // No-op for real execution.
 }
Esempio n. 25
0
 /// <summary>
 /// Notifies that a machine exited a state.
 /// </summary>
 /// <param name="machine">AbstractMachine</param>
 internal virtual void NotifyExitedState(AbstractMachine machine)
 {
     // No-op for real execution.
 }
Esempio n. 26
0
 /// <summary>
 /// Returns a fair nondeterministic boolean choice, that can be
 /// controlled during analysis or testing.
 /// </summary>
 /// <param name="machine">Machine</param>
 /// <param name="uniqueId">Unique id</param>
 /// <returns>Boolean</returns>
 internal virtual bool GetFairNondeterministicBooleanChoice(
     AbstractMachine machine, string uniqueId)
 {
     return(this.GetNondeterministicBooleanChoice(machine, 2));
 }
Esempio n. 27
0
 /// <summary>
 /// Invokes the specified monitor with the specified event.
 /// </summary>
 /// <param name="sender">Sender machine</param>
 /// <typeparam name="T">Type of the monitor</typeparam>
 /// <param name="e">Event</param>
 internal virtual void Monitor <T>(AbstractMachine sender, Event e)
 {
     // No-op for real execution.
 }
Esempio n. 28
0
 /// <summary>
 /// Sends an asynchronous event to a remote machine.
 /// </summary>
 /// <param name="sender">Sender machine</param>
 /// <param name="mid">MachineId</param>
 /// <param name="e">Event</param>
 /// <param name="isStarter">Is starting a new operation</param>
 internal virtual void SendRemotely(AbstractMachine sender, MachineId mid, Event e, bool isStarter)
 {
     this.NetworkProvider.RemoteSend(mid, e);
 }
Esempio n. 29
0
        /// <summary>
        /// Sends an asynchronous <see cref="Event"/> to a machine. Returns immediately
        /// if the target machine was already running. Otherwise blocks until the machine handles
        /// the event and reaches quiescense again.
        /// </summary>
        /// <param name="mid">MachineId</param>
        /// <param name="e">Event</param>
        /// <param name="sender">Sender machine</param>
        /// <param name="options">Optional parameters of a send operation.</param>
        /// <returns>True if event was handled, false if the event was only enqueued</returns>
        internal override async Task <bool> SendEventAndExecute(MachineId mid, Event e, AbstractMachine sender, SendOptions options)
        {
            var operationGroupId = base.GetNewOperationGroupId(sender, options?.OperationGroupId);

            if (!base.GetTargetMachine(mid, e, sender, operationGroupId, out Machine machine))
            {
                return(true);
            }

            bool runNewHandler = false;

            this.EnqueueEvent(machine, e, sender, operationGroupId, ref runNewHandler);
            if (runNewHandler)
            {
                await this.RunMachineEventHandlerAsync(machine, null, false);

                return(true);
            }
            return(false);
        }
Esempio n. 30
0
 /// <summary>
 /// Sends an asynchronous <see cref="Event"/> to a remote machine.
 /// </summary>
 /// <param name="mid">MachineId</param>
 /// <param name="e">Event</param>
 /// <param name="sender">Sender machine</param>
 /// <param name="options">Optional parameters of a send operation.</param>
 internal override void SendEventRemotely(MachineId mid, Event e, AbstractMachine sender, SendOptions options)
 {
     base.NetworkProvider.RemoteSend(mid, e);
 }