Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityResource.cs @ 16779

Last change on this file since 16779 was 16779, checked in by abeham, 5 years ago

#2975: Updated Sim# to 3.1.1

File size: 6.1 KB
Line 
1#region License Information
2/* SimSharp - A .NET port of SimPy, discrete event simulation framework
3Copyright (C) 2019  Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4
5This program is free software: you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation, either version 3 of the License, or
8(at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
17#endregion
18
19using System;
20using System.Collections.Generic;
21
22namespace SimSharp {
23  /// <summary>
24  /// A PriorityResource is similar to a <see cref="Resource"/>.
25  /// However, it enables prioritizing requests.
26  ///
27  /// PriorityResource holds a fixed number of anonymous entities.
28  /// Requests are processed in order priority first, FIFO second.
29  /// Releases are processed in FIFO order (usually no simulation time passes for a Release).
30  /// </summary>
31  public class PriorityResource {
32
33    public int Capacity { get; protected set; }
34
35    public int InUse { get { return Users.Count; } }
36
37    public int Remaining { get { return Capacity - InUse; } }
38
39    protected Simulation Environment { get; private set; }
40
41    protected SimplePriorityQueue<Request, double> RequestQueue { get; private set; }
42    protected Queue<Release> ReleaseQueue { get; private set; }
43    protected HashSet<Request> Users { get; private set; }
44    protected List<Event> WhenAnyQueue { get; private set; }
45    protected List<Event> WhenFullQueue { get; private set; }
46    protected List<Event> WhenEmptyQueue { get; private set; }
47    protected List<Event> WhenChangeQueue { get; private set; }
48
49    public PriorityResource(Simulation environment, int capacity = 1) {
50      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0.", "capacity");
51      Environment = environment;
52      Capacity = capacity;
53      RequestQueue = new SimplePriorityQueue<Request, double>();
54      ReleaseQueue = new Queue<Release>();
55      Users = new HashSet<Request>();
56      WhenAnyQueue = new List<Event>();
57      WhenFullQueue = new List<Event>();
58      WhenEmptyQueue = new List<Event>();
59      WhenChangeQueue = new List<Event>();
60    }
61
62    public virtual Request Request(double priority = 1) {
63      var request = new Request(Environment, TriggerRelease, DisposeCallback);
64      RequestQueue.Enqueue(request, priority);
65      TriggerRequest();
66      return request;
67    }
68
69    public virtual Release Release(Request request) {
70      var release = new Release(Environment, request, TriggerRequest);
71      ReleaseQueue.Enqueue(release);
72      TriggerRelease();
73      return release;
74    }
75
76    public virtual Event WhenAny() {
77      var whenAny = new Event(Environment);
78      WhenAnyQueue.Add(whenAny);
79      TriggerWhenAny();
80      return whenAny;
81    }
82
83    public virtual Event WhenFull() {
84      var whenFull = new Event(Environment);
85      WhenFullQueue.Add(whenFull);
86      TriggerWhenFull();
87      return whenFull;
88    }
89
90    public virtual Event WhenEmpty() {
91      var whenEmpty = new Event(Environment);
92      WhenEmptyQueue.Add(whenEmpty);
93      TriggerWhenEmpty();
94      return whenEmpty;
95    }
96
97    public virtual Event WhenChange() {
98      var whenChange = new Event(Environment);
99      WhenChangeQueue.Add(whenChange);
100      return whenChange;
101    }
102
103    protected void DisposeCallback(Event @event) {
104      var request = @event as Request;
105      if (request != null) Release(request);
106    }
107
108    protected virtual void DoRequest(Request request) {
109      if (Users.Count < Capacity) {
110        Users.Add(request);
111        request.Succeed();
112      }
113    }
114
115    protected virtual void DoRelease(Release release) {
116      if (!Users.Remove(release.Request))
117        throw new InvalidOperationException("Released request does not have a user.");
118      release.Succeed();
119    }
120
121    protected virtual void TriggerRequest(Event @event = null) {
122      while (RequestQueue.Count > 0) {
123        var request = RequestQueue.First;
124        DoRequest(request);
125        if (request.IsTriggered) {
126          RequestQueue.Dequeue();
127          TriggerWhenEmpty();
128          TriggerWhenChange();
129        } else break;
130      }
131    }
132
133    protected virtual void TriggerRelease(Event @event = null) {
134      while (ReleaseQueue.Count > 0) {
135        var release = ReleaseQueue.Peek();
136        if (release.Request.IsAlive) {
137          if (!RequestQueue.TryRemove(release.Request))
138            throw new InvalidOperationException("Failed to cancel a request.");
139          release.Succeed();
140          ReleaseQueue.Dequeue();
141        }
142        DoRelease(release);
143        if (release.IsTriggered) {
144          ReleaseQueue.Dequeue();
145          TriggerWhenAny();
146          TriggerWhenFull();
147          TriggerWhenChange();
148        } else break;
149      }
150    }
151
152    protected virtual void TriggerWhenAny() {
153      if (Remaining > 0) {
154        if (WhenAnyQueue.Count == 0) return;
155        foreach (var evt in WhenAnyQueue)
156          evt.Succeed();
157        WhenAnyQueue.Clear();
158      }
159    }
160
161    protected virtual void TriggerWhenFull() {
162      if (InUse == 0) {
163        if (WhenFullQueue.Count == 0) return;
164        foreach (var evt in WhenFullQueue)
165          evt.Succeed();
166        WhenFullQueue.Clear();
167      }
168    }
169
170    protected virtual void TriggerWhenEmpty() {
171      if (Remaining == 0) {
172        if (WhenEmptyQueue.Count == 0) return;
173        foreach (var evt in WhenEmptyQueue)
174          evt.Succeed();
175        WhenEmptyQueue.Clear();
176      }
177    }
178
179    protected virtual void TriggerWhenChange() {
180      if (WhenChangeQueue.Count == 0) return;
181      foreach (var evt in WhenChangeQueue)
182        evt.Succeed();
183      WhenChangeQueue.Clear();
184    }
185  }
186}
Note: See TracBrowser for help on using the repository browser.