示例#1
0
 public Process(Environment environment, IEnumerable<Event> generator)
     : base(environment)
 {
     this.generator = generator.GetEnumerator();
       IsOk = true;
       target = new Initialize(environment, this);
 }
示例#2
0
 protected virtual void CollectValues(Event @event) {
   if (@event.IsOk) {
     var value = new OrderedDictionary();
     foreach (var v in GetValues())
       value.Add(v.Key, v.Value);
     Value = value;
   }
 }
示例#3
0
 protected virtual void TriggerRequest(Event @event = null) {
   while (RequestQueue.Count > 0) {
     var request = RequestQueue.Peek();
     DoRequest(request);
     if (request.IsTriggered) {
       RequestQueue.Dequeue();
     } else break;
   }
 }
示例#4
0
 protected virtual void TriggerGet(Event @event = null) {
   while (GetQueue.Count > 0) {
     var get = GetQueue.Peek();
     DoGet(get);
     if (get.IsTriggered) {
       GetQueue.Dequeue();
     } else break;
   }
 }
示例#5
0
 protected virtual void TriggerPut(Event @event = null) {
   while (PutQueue.Count > 0) {
     var put = PutQueue.Peek();
     DoPut(put);
     if (put.IsTriggered) {
       PutQueue.Dequeue();
     } else break;
   }
 }
示例#6
0
 protected virtual void TriggerRequest(Event @event = null) {
   while (RequestQueue.Count > 0) {
     var request = RequestQueue.First.Value;
     DoRequest(request);
     if (request.IsTriggered) {
       RequestQueue.RemoveFirst();
     } else break;
   }
 }
示例#7
0
    /// <summary>
    /// This interrupts a process and causes the IsOk flag to be set to false.
    /// If a process is interrupted the iterator method needs to call HandleFault()
    /// before continuing to yield further events.
    /// </summary>
    /// <exception cref="InvalidOperationException">This is thrown in three conditions:
    ///  - If the process has already been triggered.
    ///  - If the process attempts to interrupt itself.
    ///  - If the process continues to yield events despite being faulted.</exception>
    /// <param name="cause">The cause of the interrupt.</param>
    public virtual void Interrupt(object cause = null) {
      if (IsTriggered) throw new InvalidOperationException("The process has terminated and cannot be interrupted.");
      if (Environment.ActiveProcess == this) throw new InvalidOperationException("A process is not allowed to interrupt itself.");

      var interruptEvent = new Event(Environment);
      interruptEvent.AddCallback(Resume);
      interruptEvent.Fail(cause);

      if (Target != null)
        Target.RemoveCallback(Resume);
    }
示例#8
0
 protected virtual void TriggerRequest(Event @event = null) {
   var current = RequestQueue.First;
   while (current != null) {
     var request = current.Value;
     DoRequest(request);
     if (request.IsTriggered) {
       var next = current.Next;
       RequestQueue.Remove(current);
       current = next;
     }
     if (Resources.Count == 0) break;
   }
 }
示例#9
0
    protected void Check(Event @event) {
      if (IsTriggered || IsProcessed) {
        if ([email protected]) throw new InvalidOperationException(
@"Errors that happen after the condition has been triggered will not be
handled by the condition and cause the simulation to crash.");
        return;
      }
      FiredEvents.Add(@event);

      if ([email protected])
        Fail(@event.Value);
      else if (Evaluate()) {
        Succeed();
      }
    }
示例#10
0
 protected virtual void TriggerRequest(Event @event = null) {
   foreach (var entry in RequestQueue) {
     var cascade = false;
     var requests = entry.Value;
     while (requests.Count > 0) {
       var req = requests.Peek();
       DoRequest(req);
       if (req.IsTriggered) {
         requests.Dequeue();
       } else {
         cascade = true;
         break;
       }
     }
     if (cascade) break;
   }
 }
示例#11
0
    protected virtual void Resume(Event @event) {
      Environment.ActiveProcess = this;
      while (true) {
        if (@event.IsOk) {
          if (generator.MoveNext()) {
            if (IsTriggered) {
              // the generator called e.g. Environment.ActiveProcess.Fail
              Environment.ActiveProcess = null;
              return;
            }
            if (ProceedToEvent()) break;
          } else if (!IsTriggered) {
            Succeed(@event.Value);
            break;
          } else break;
        } else {
          /* Fault handling differs from SimPy as in .NET it is not possible to inject an
         * exception into an enumerator and it is impossible to put a yield return inside
         * a try-catch block. In SimSharp the Process will set IsOk and will then move to
         * the next yield in the generator. However, if after this move IsOk is still false
         * we know that the error was not handled. It is assumed the error is handled if
         * HandleFault() is called on the environment's ActiveProcess which will reset the
         * flag. */
          IsOk = false;
          Value = @event.Value;

          if (generator.MoveNext()) {
            if (IsTriggered) {
              // the generator called e.g. Environment.ActiveProcess.Fail
              Environment.ActiveProcess = null;
              return;
            }
            // if we move next, but IsOk is still false
            if (!IsOk) throw new InvalidOperationException("The process did not react to being faulted.");
            // otherwise HandleFault was called and the fault was handled
            if (ProceedToEvent()) break;
          } else if (!IsTriggered) {
            if (!IsOk) Fail(@event.Value);
            else Succeed(@event.Value);
            break;
          } else break;
        }
      }
      Environment.ActiveProcess = null;
    }
示例#12
0
 public virtual void ScheduleD(double delay, Event @event) {
   Schedule(TimeSpan.FromSeconds(DefaultTimeStepSeconds * delay), @event);
 }
示例#13
0
 protected virtual void StopSimulation(Event @event) {
   throw new StopSimulationException(@event.Value);
 }
示例#14
0
    public virtual object Run(Event stopEvent = null) {
      if (stopEvent != null) {
        if (stopEvent.IsProcessed) return stopEvent.Value;
        stopEvent.AddCallback(StopSimulation);
      }

      try {
        var stop = Queue.Count == 0 && ScheduleQ.Count == 0;
        while (!stop) {
          Step();
          ProcessedEvents++;
          lock (locker) {
            stop = Queue.Count == 0 && ScheduleQ.Count == 0;
          }
        }
      } catch (StopSimulationException e) { return e.Value; }
      if (stopEvent == null) return null;
      if (!stopEvent.IsTriggered) throw new InvalidOperationException("No scheduled events left but \"until\" event was not triggered.");
      return stopEvent.Value;
    }
示例#15
0
 protected virtual void TriggerRelease(Event @event = null) {
   while (ReleaseQueue.Count > 0) {
     var release = ReleaseQueue.Peek();
     DoRelease(release);
     if (release.IsTriggered) {
       ReleaseQueue.Dequeue();
     } else break;
   }
 }
示例#16
0
 protected virtual bool ProceedToEvent()
 {
     target = generator.Current;
       Value = target.Value;
       if (target.IsProcessed) return false;
       target.AddCallback(Resume);
       return true;
 }
示例#17
0
 /// <summary>
 /// This method schedules the event right now. It takes the IsOk state
 /// and uses the <see cref="Value"/> of the given <paramref name="@event"/>.
 /// Thus if the given event fails, this event will also be triggered as
 /// failing.
 /// </summary>
 /// <exception cref="InvalidOperationException">
 /// Thrown when the event has already been triggered.
 /// </exception>
 /// <remarks>
 /// The signature of this method allows it to be used as a callback.
 /// </remarks>
 /// <param name="event">The event that triggers this event.</param>
 public virtual void Trigger(Event @event) {
   if (IsTriggered)
     throw new InvalidOperationException("Event has already been triggered.");
   IsOk = @event.IsOk;
   Value = @event.Value;
   IsTriggered = true;
   Environment.Schedule(this);
 }
示例#18
0
 protected virtual void TriggerGet(Event @event = null) {
   var current = GetQueue.First;
   while (current != null) {
     var get = current.Value;
     DoGet(get);
     if (get.IsTriggered) {
       var next = current.Next;
       GetQueue.Remove(current);
       current = next;
     } else current = current.Next;
     if (Items.Count == 0) break;
   }
 }
示例#19
0
 public virtual void Schedule(Event @event) {
   lock (locker) {
     Queue.Enqueue(@event);
   }
 }
示例#20
0
 protected virtual void DisposeCallback(Event @event) {
   var request = @event as Request;
   if (request != null) Release(request);
 }
示例#21
0
 public virtual void Schedule(TimeSpan delay, Event @event) {
   if (delay < TimeSpan.Zero)
     throw new ArgumentException("Negative delays are not allowed in Schedule(TimeSpan, Event).");
   lock (locker) {
     if (delay == TimeSpan.Zero) {
       Queue.Enqueue(@event);
       return;
     }
     var eventTime = Now + delay;
     DoSchedule(eventTime, @event);
   }
 }
示例#22
0
 protected virtual void TriggerRequest(Event @event = null) {
   foreach (var entry in RequestQueue) {
     var requests = entry.Value;
     var current = requests.First;
     while (current != null) {
       var request = current.Value;
       DoRequest(request);
       if (request.IsTriggered) {
         var next = current.Next;
         requests.Remove(current);
         current = next;
       } else current = current.Next;
     }
   }
 }
示例#23
0
 protected virtual EventQueueNode DoSchedule(DateTime date, Event @event) {
   if (ScheduleQ.MaxSize == ScheduleQ.Count) {
     // the capacity has to be adjusted, there are more events in the queue than anticipated
     var oldSchedule = ScheduleQ;
     ScheduleQ = new EventQueue(ScheduleQ.MaxSize * 2);
     foreach (var e in oldSchedule) ScheduleQ.Enqueue(e.Priority, e.Event);
   }
   return ScheduleQ.Enqueue(date, @event);
 }
示例#24
0
 protected void DisposeCallback(Event @event) {
   var request = @event as PreemptiveRequest;
   if (request != null) Release(request);
 }
示例#25
0
 public virtual object Run(DateTime until) {
   if (until <= Now) throw new InvalidOperationException("Simulation end date must lie in the future.");
   var stopEvent = new Event(this);
   var node = DoSchedule(until, stopEvent);
   // stop event is always the first to execute at the given time
   node.InsertionIndex = -1;
   ScheduleQ.OnNodeUpdated(node);
   return Run(stopEvent);
 }