Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.3.1/SimSharp-3.3.1/Core/Resources/ResourcePool.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.9 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;
10using System.Linq;
11
12namespace SimSharp {
13  /// <summary>
14  /// A ResourcePool is a crossover between a <see cref="Resource"/> and a <see cref="Store"/>.
15  /// There is a fixed number of non-anonymous resources.
16  ///
17  /// Requests are performed in FIFO order only when they match at least one resource in the pool.
18  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
19  /// </summary>
20  public class ResourcePool {
21    protected static readonly Func<object, bool> TrueFunc = _ => true;
22
23    public int Capacity { get; protected set; }
24
25    public int InUse { get { return Capacity - Remaining; } }
26
27    public int Remaining { get { return Resources.Count; } }
28
29    protected Simulation Environment { get; private set; }
30
31    protected LinkedList<ResourcePoolRequest> RequestQueue { get; private set; }
32    protected Queue<Release> ReleaseQueue { get; private set; }
33    protected List<object> Resources { get; private set; }
34    protected List<Event> WhenAnyQueue { get; private set; }
35    protected List<Event> WhenFullQueue { get; private set; }
36    protected List<Event> WhenEmptyQueue { get; private set; }
37    protected List<Event> WhenChangeQueue { get; private set; }
38
39    public ITimeSeriesMonitor Utilization { get; set; }
40    public ITimeSeriesMonitor WIP { get; set; }
41    public ITimeSeriesMonitor QueueLength { get; set; }
42    public ISampleMonitor LeadTime { get; set; }
43    public ISampleMonitor WaitingTime { get; set; }
44    public ISampleMonitor BreakOffTime { get; set; }
45
46    public ResourcePool(Simulation environment, IEnumerable<object> resources) {
47      Environment = environment;
48      if (resources == null) throw new ArgumentNullException("resources");
49      Resources = new List<object>(resources);
50      Capacity = Resources.Count;
51      if (Capacity == 0) throw new ArgumentException("There must be at least one resource", "resources");
52      RequestQueue = new LinkedList<ResourcePoolRequest>();
53      ReleaseQueue = new Queue<Release>();
54      WhenAnyQueue = new List<Event>();
55      WhenFullQueue = new List<Event>();
56      WhenEmptyQueue = new List<Event>();
57      WhenChangeQueue = new List<Event>();
58    }
59
60    public virtual bool IsAvailable(Func<object, bool> filter) {
61      return Resources.Any(filter);
62    }
63
64    public virtual ResourcePoolRequest Request(Func<object, bool> filter = null) {
65      var request = new ResourcePoolRequest(Environment, TriggerRelease, DisposeCallback, filter ?? TrueFunc);
66      RequestQueue.AddLast(request);
67      TriggerRequest();
68      return request;
69    }
70
71    public virtual Release Release(Request request) {
72      var release = new Release(Environment, request, TriggerRequest);
73      ReleaseQueue.Enqueue(release);
74      TriggerRelease();
75      return release;
76    }
77
78    public virtual Event WhenAny() {
79      var whenAny = new Event(Environment);
80      WhenAnyQueue.Add(whenAny);
81      TriggerWhenAny();
82      return whenAny;
83    }
84
85    public virtual Event WhenFull() {
86      var whenFull = new Event(Environment);
87      WhenFullQueue.Add(whenFull);
88      TriggerWhenFull();
89      return whenFull;
90    }
91
92    public virtual Event WhenEmpty() {
93      var whenEmpty = new Event(Environment);
94      WhenEmptyQueue.Add(whenEmpty);
95      TriggerWhenEmpty();
96      return whenEmpty;
97    }
98
99    public virtual Event WhenChange() {
100      var whenChange = new Event(Environment);
101      WhenChangeQueue.Add(whenChange);
102      return whenChange;
103    }
104
105    protected virtual void DisposeCallback(Event @event) {
106      var request = @event as Request;
107      if (request != null) Release(request);
108    }
109
110    protected virtual void DoRequest(ResourcePoolRequest request) {
111      foreach (var o in Resources) {
112        if (!request.Filter(o)) continue;
113        WaitingTime?.Add(Environment.ToDouble(Environment.Now - request.Time));
114        Resources.Remove(o);
115        request.Succeed(o);
116        return;
117      }
118    }
119
120    protected virtual void DoRelease(Release release) {
121      Resources.Add(release.Request.Value);
122      LeadTime?.Add(Environment.ToDouble(Environment.Now - release.Request.Time));
123      release.Succeed();
124    }
125
126    protected virtual void TriggerRequest(Event @event = null) {
127      var current = RequestQueue.First;
128      while (current != null) {
129        var request = current.Value;
130        DoRequest(request);
131        if (request.IsTriggered) {
132          var next = current.Next;
133          RequestQueue.Remove(current);
134          current = next;
135          TriggerWhenEmpty();
136          TriggerWhenChange();
137        } else current = current.Next;
138        if (Resources.Count == 0) break;
139      }
140      Utilization?.UpdateTo(InUse / (double)Capacity);
141      WIP?.UpdateTo(InUse + RequestQueue.Count);
142      QueueLength?.UpdateTo(RequestQueue.Count);
143    }
144
145    protected virtual void TriggerRelease(Event @event = null) {
146      while (ReleaseQueue.Count > 0) {
147        var release = ReleaseQueue.Peek();
148        if (release.Request.IsAlive) {
149          if (!RequestQueue.Remove((ResourcePoolRequest)release.Request))
150            throw new InvalidOperationException("Failed to cancel a request.");
151          BreakOffTime?.Add(Environment.ToDouble(Environment.Now - release.Request.Time));
152          release.Succeed();
153          ReleaseQueue.Dequeue();
154        } else {
155          DoRelease(release);
156          if (release.IsTriggered) {
157            ReleaseQueue.Dequeue();
158            TriggerWhenAny();
159            TriggerWhenFull();
160            TriggerWhenChange();
161          } else break;
162        }
163      }
164      Utilization?.UpdateTo(InUse / (double)Capacity);
165      WIP?.UpdateTo(InUse + RequestQueue.Count);
166      QueueLength?.UpdateTo(RequestQueue.Count);
167    }
168
169    protected virtual void TriggerWhenAny() {
170      if (Remaining > 0) {
171        if (WhenAnyQueue.Count == 0) return;
172        foreach (var evt in WhenAnyQueue)
173          evt.Succeed();
174        WhenAnyQueue.Clear();
175      }
176    }
177
178    protected virtual void TriggerWhenFull() {
179      if (InUse == 0) {
180        if (WhenFullQueue.Count == 0) return;
181        foreach (var evt in WhenFullQueue)
182          evt.Succeed();
183        WhenFullQueue.Clear();
184      }
185    }
186
187    protected virtual void TriggerWhenEmpty() {
188      if (Remaining == 0) {
189        if (WhenEmptyQueue.Count == 0) return;
190        foreach (var evt in WhenEmptyQueue)
191          evt.Succeed();
192        WhenEmptyQueue.Clear();
193      }
194    }
195
196    protected virtual void TriggerWhenChange() {
197      if (WhenChangeQueue.Count == 0) return;
198      foreach (var evt in WhenChangeQueue)
199        evt.Succeed();
200      WhenChangeQueue.Clear();
201    }
202  }
203}
Note: See TracBrowser for help on using the repository browser.