Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.3.1/SimSharp-3.3.1/Core/Resources/Resource.cs @ 17487

Last change on this file since 17487 was 17487, checked in by abeham, 4 years ago

#3065: update Sim# to 3.3.1

File size: 6.2 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 resource holds a fixed number of anonymous entities.
14  ///
15  /// Requests are processed in FIFO order.
16  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
17  /// </summary>
18  public class Resource {
19
20    public int Capacity { get; protected set; }
21
22    public int InUse { get { return Users.Count; } }
23
24    public int Remaining { get { return Capacity - InUse; } }
25
26    protected Simulation Environment { get; private set; }
27
28    protected LinkedList<Request> RequestQueue { get; private set; }
29    protected Queue<Release> ReleaseQueue { get; private set; }
30    protected HashSet<Request> Users { get; private set; }
31    protected List<Event> WhenAnyQueue { get; private set; }
32    protected List<Event> WhenFullQueue { get; private set; }
33    protected List<Event> WhenEmptyQueue { get; private set; }
34    protected List<Event> WhenChangeQueue { get; private set; }
35
36    public ITimeSeriesMonitor Utilization { get; set; }
37    public ITimeSeriesMonitor WIP { get; set; }
38    public ITimeSeriesMonitor QueueLength { get; set; }
39    public ISampleMonitor LeadTime { get; set; }
40    public ISampleMonitor WaitingTime { get; set; }
41    public ISampleMonitor BreakOffTime { get; set; }
42
43    public Resource(Simulation environment, int capacity = 1) {
44      if (capacity <= 0) throw new ArgumentException("Capacity must > 0.", "capacity");
45      Environment = environment;
46      Capacity = capacity;
47      RequestQueue = new LinkedList<Request>();
48      ReleaseQueue = new Queue<Release>();
49      Users = new HashSet<Request>();
50      WhenAnyQueue = new List<Event>();
51      WhenFullQueue = new List<Event>();
52      WhenEmptyQueue = new List<Event>();
53      WhenChangeQueue = new List<Event>();
54    }
55
56    public virtual Request Request() {
57      var request = new Request(Environment, TriggerRelease, DisposeCallback);
58      RequestQueue.AddLast(request);
59      TriggerRequest();
60      return request;
61    }
62
63    public virtual Release Release(Request request) {
64      var release = new Release(Environment, request, TriggerRequest);
65      ReleaseQueue.Enqueue(release);
66      TriggerRelease();
67      return release;
68    }
69
70    public virtual Event WhenAny() {
71      var whenAny = new Event(Environment);
72      WhenAnyQueue.Add(whenAny);
73      TriggerWhenAny();
74      return whenAny;
75    }
76
77    public virtual Event WhenFull() {
78      var whenFull = new Event(Environment);
79      WhenFullQueue.Add(whenFull);
80      TriggerWhenFull();
81      return whenFull;
82    }
83
84    public virtual Event WhenEmpty() {
85      var whenEmpty = new Event(Environment);
86      WhenEmptyQueue.Add(whenEmpty);
87      TriggerWhenEmpty();
88      return whenEmpty;
89    }
90
91    public virtual Event WhenChange() {
92      var whenChange = new Event(Environment);
93      WhenChangeQueue.Add(whenChange);
94      return whenChange;
95    }
96
97    protected virtual void DisposeCallback(Event @event) {
98      var request = @event as Request;
99      if (request != null) {
100        Release(request);
101      }
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.Value;
122        DoRequest(request);
123        if (request.IsTriggered) {
124          RequestQueue.RemoveFirst();
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.Remove(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        } else {
144          DoRelease(release);
145          if (release.IsTriggered) {
146            ReleaseQueue.Dequeue();
147            TriggerWhenAny();
148            TriggerWhenFull();
149            TriggerWhenChange();
150          } else break;
151        }
152      }
153      Utilization?.UpdateTo(InUse / (double)Capacity);
154      WIP?.UpdateTo(InUse + RequestQueue.Count);
155      QueueLength?.UpdateTo(RequestQueue.Count);
156    }
157
158    protected virtual void TriggerWhenAny() {
159      if (Remaining > 0) {
160        if (WhenAnyQueue.Count == 0) return;
161        foreach (var evt in WhenAnyQueue)
162          evt.Succeed();
163        WhenAnyQueue.Clear();
164      }
165    }
166
167    protected virtual void TriggerWhenFull() {
168      if (InUse == 0) {
169        if (WhenFullQueue.Count == 0) return;
170        foreach (var evt in WhenFullQueue)
171          evt.Succeed();
172        WhenFullQueue.Clear();
173      }
174    }
175
176    protected virtual void TriggerWhenEmpty() {
177      if (Remaining == 0) {
178        if (WhenEmptyQueue.Count == 0) return;
179        foreach (var evt in WhenEmptyQueue)
180          evt.Succeed();
181        WhenEmptyQueue.Clear();
182      }
183    }
184
185    protected virtual void TriggerWhenChange() {
186      if (WhenChangeQueue.Count == 0) return;
187      foreach (var evt in WhenChangeQueue)
188        evt.Succeed();
189      WhenChangeQueue.Clear();
190    }
191  }
192}
Note: See TracBrowser for help on using the repository browser.