Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.3.2/SimSharp-3.3.2/Core/Resources/PriorityResource.cs @ 18023

Last change on this file since 18023 was 18023, checked in by jkarder, 3 years ago

#3065: update Sim# to 3.3.2

File size: 6.1 KB
Line 
1#region License Information
2/*
3 * This file is part of SimSharp which is licensed under the MIT license.
4 * See the LICENSE file in the project root for more information.
5 */
6#endregion
7
8using System;
9using System.Collections.Generic;
10
11namespace SimSharp {
12  /// <summary>
13  /// A PriorityResource is similar to a <see cref="Resource"/>.
14  /// However, it enables prioritizing requests.
15  ///
16  /// PriorityResource holds a fixed number of anonymous entities.
17  /// Requests are processed in order priority first, FIFO second.
18  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
19  /// </summary>
20  public class PriorityResource {
21
22    public int Capacity { get; protected set; }
23
24    public int InUse { get { return Users.Count; } }
25
26    public int Remaining { get { return Capacity - InUse; } }
27
28    protected Simulation Environment { get; private set; }
29
30    protected SimplePriorityQueue<Request, double> RequestQueue { get; private set; }
31    protected Queue<Release> ReleaseQueue { get; private set; }
32    protected HashSet<Request> Users { get; private set; }
33    protected List<Event> WhenAnyQueue { get; private set; }
34    protected List<Event> WhenFullQueue { get; private set; }
35    protected List<Event> WhenEmptyQueue { get; private set; }
36    protected List<Event> WhenChangeQueue { get; private set; }
37
38    public ITimeSeriesMonitor Utilization { get; set; }
39    public ITimeSeriesMonitor WIP { get; set; }
40    public ITimeSeriesMonitor QueueLength { get; set; }
41    public ISampleMonitor LeadTime { get; set; }
42    public ISampleMonitor WaitingTime { get; set; }
43    public ISampleMonitor BreakOffTime { get; set; }
44
45    public PriorityResource(Simulation environment, int capacity = 1) {
46      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0.", "capacity");
47      Environment = environment;
48      Capacity = capacity;
49      RequestQueue = new SimplePriorityQueue<Request, double>();
50      ReleaseQueue = new Queue<Release>();
51      Users = new HashSet<Request>();
52      WhenAnyQueue = new List<Event>();
53      WhenFullQueue = new List<Event>();
54      WhenEmptyQueue = new List<Event>();
55      WhenChangeQueue = new List<Event>();
56    }
57
58    public virtual Request Request(double priority = 1) {
59      var request = new Request(Environment, TriggerRelease, DisposeCallback);
60      RequestQueue.Enqueue(request, priority);
61      TriggerRequest();
62      return request;
63    }
64
65    public virtual Release Release(Request request) {
66      var release = new Release(Environment, request, TriggerRequest);
67      ReleaseQueue.Enqueue(release);
68      TriggerRelease();
69      return release;
70    }
71
72    public virtual Event WhenAny() {
73      var whenAny = new Event(Environment);
74      WhenAnyQueue.Add(whenAny);
75      TriggerWhenAny();
76      return whenAny;
77    }
78
79    public virtual Event WhenFull() {
80      var whenFull = new Event(Environment);
81      WhenFullQueue.Add(whenFull);
82      TriggerWhenFull();
83      return whenFull;
84    }
85
86    public virtual Event WhenEmpty() {
87      var whenEmpty = new Event(Environment);
88      WhenEmptyQueue.Add(whenEmpty);
89      TriggerWhenEmpty();
90      return whenEmpty;
91    }
92
93    public virtual Event WhenChange() {
94      var whenChange = new Event(Environment);
95      WhenChangeQueue.Add(whenChange);
96      return whenChange;
97    }
98
99    protected void DisposeCallback(Event @event) {
100      var request = @event as Request;
101      if (request != null) Release(request);
102    }
103
104    protected virtual void DoRequest(Request request) {
105      if (Users.Count < Capacity) {
106        WaitingTime?.Add(Environment.ToDouble(Environment.Now - request.Time));
107        Users.Add(request);
108        request.Succeed();
109      }
110    }
111
112    protected virtual void DoRelease(Release release) {
113      if (!Users.Remove(release.Request))
114        throw new InvalidOperationException("Released request does not have a user.");
115      LeadTime?.Add(Environment.ToDouble(Environment.Now - release.Request.Time));
116      release.Succeed();
117    }
118
119    protected virtual void TriggerRequest(Event @event = null) {
120      while (RequestQueue.Count > 0) {
121        var request = RequestQueue.First;
122        DoRequest(request);
123        if (request.IsTriggered) {
124          RequestQueue.Dequeue();
125          TriggerWhenEmpty();
126          TriggerWhenChange();
127        } else break;
128      }
129      Utilization?.UpdateTo(InUse / (double)Capacity);
130      WIP?.UpdateTo(InUse + RequestQueue.Count);
131      QueueLength?.UpdateTo(RequestQueue.Count);
132    }
133
134    protected virtual void TriggerRelease(Event @event = null) {
135      while (ReleaseQueue.Count > 0) {
136        var release = ReleaseQueue.Peek();
137        if (release.Request.IsAlive) {
138          if (!RequestQueue.TryRemove(release.Request))
139            throw new InvalidOperationException("Failed to cancel a request.");
140          BreakOffTime?.Add(Environment.ToDouble(Environment.Now - release.Request.Time));
141          release.Succeed();
142          ReleaseQueue.Dequeue();
143        }
144        DoRelease(release);
145        if (release.IsTriggered) {
146          ReleaseQueue.Dequeue();
147          TriggerWhenAny();
148          TriggerWhenFull();
149          TriggerWhenChange();
150        } else break;
151      }
152      Utilization?.UpdateTo(InUse / (double)Capacity);
153      WIP?.UpdateTo(InUse + RequestQueue.Count);
154      QueueLength?.UpdateTo(RequestQueue.Count);
155    }
156
157    protected virtual void TriggerWhenAny() {
158      if (Remaining > 0) {
159        if (WhenAnyQueue.Count == 0) return;
160        foreach (var evt in WhenAnyQueue)
161          evt.Succeed();
162        WhenAnyQueue.Clear();
163      }
164    }
165
166    protected virtual void TriggerWhenFull() {
167      if (InUse == 0) {
168        if (WhenFullQueue.Count == 0) return;
169        foreach (var evt in WhenFullQueue)
170          evt.Succeed();
171        WhenFullQueue.Clear();
172      }
173    }
174
175    protected virtual void TriggerWhenEmpty() {
176      if (Remaining == 0) {
177        if (WhenEmptyQueue.Count == 0) return;
178        foreach (var evt in WhenEmptyQueue)
179          evt.Succeed();
180        WhenEmptyQueue.Clear();
181      }
182    }
183
184    protected virtual void TriggerWhenChange() {
185      if (WhenChangeQueue.Count == 0) return;
186      foreach (var evt in WhenChangeQueue)
187        evt.Succeed();
188      WhenChangeQueue.Clear();
189    }
190  }
191}
Note: See TracBrowser for help on using the repository browser.