Esempio n. 1
0
        /// <summary>
        ///   Updates current steps, so that <see cref="IInternalCall.Steps"/> are used instead.
        ///   Moreover, it adjusts the stack of calls, since that is necessary to maintain integrity.
        /// </summary>
        /// <param name="call">The call from which new steps are taken.</param>
        internal void PushCall(IInternalCall call)
        {
            var tmp = call.Steps;

            call.Steps        = _steps;
            _steps            = tmp;
            call.PreviousCall = _currentCall;
            _currentCall      = call;
        }
Esempio n. 2
0
        /// <summary>
        ///   Called when this event is the first in the agenda.
        /// </summary>
        internal override void Step()
        {
            // Target has to be cleaned before process is started up again.
            Target = null;

            // In SimPy 3, interrupts are sent to processes as exceptions.
            // However, this cannot be done in .NET; therefore, we dediced to throw
            // an exception if a process was interrupted, but it did not check for that.
            // To achieve this, we need to record the number of interrupts
            // this process has and we will see if it has properly decreased.
            var oldInterruptCount = _interruptCount;

            // We start the process again and see if it produces more events.
            if (_steps.MoveNext() && !ReferenceEquals(Target = _steps.Current, Env.EndEvent))
            {
                // User has yielded an event. Since users may yield null events,
                // we need to check for them, as they are not allowed.
                if (Target == null)
                {
                    throw new ArgumentNullException(ErrorMessages.NullEvent);
                }
                // If the interrupt count was zero, then we have nothing more to check.
                // Otherwise, we will need to check that it was decreased at least by one.
                if (oldInterruptCount != 0 && _interruptCount == oldInterruptCount)
                {
                    throw new InterruptUncaughtException();
                }
                Target.Subscribe(this);
                return;
            }

            // Body of generator has finished, therefore process or call has finished.
            // If the interrupt count was zero, then we have nothing more to check.
            // Otherwise, we will need to check that it was decreased at least by one.
            if (oldInterruptCount != 0 && _interruptCount == oldInterruptCount)
            {
                throw new InterruptUncaughtException();
            }

            // If target event is the end event, then the process should exit,
            // no matter how many interrupts have been received.
            if (_currentCall != null)
            {
                _steps       = _currentCall.Steps;
                _currentCall = _currentCall.PreviousCall;
            }
            else
            {
                // We have to remove current process from the agenda.
                Env.UnscheduleActiveProcess();
                // Marks this event as succeeded, as processes cannot fail.
                End();
            }
        }