Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/PriorityStore.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: 7.2 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;
21using System.Linq;
22
23namespace SimSharp {
24  /// <summary>
25  /// A PriorityStore is similar to a <see cref="Store"/>.
26  /// However, items are removed from the store in order of their priority.
27  ///
28  /// PriorityStore holds a variable number of individual items.
29  /// Put and Get are both processed in strict FIFO order.
30  /// </summary>
31  public class PriorityStore {
32
33    public int Capacity { get; protected set; }
34
35    public int Count { get { return Items.Count; } }
36
37    protected Simulation Environment { get; private set; }
38
39    protected Queue<StorePut> PutQueue { get; private set; }
40    protected Queue<StoreGet> GetQueue { get; private set; }
41    protected SimplePriorityQueue<object, double> Items { get; private set; }
42    protected List<Event> WhenNewQueue { get; private set; }
43    protected List<Event> WhenAnyQueue { get; private set; }
44    protected List<Event> WhenFullQueue { get; private set; }
45    protected List<Event> WhenEmptyQueue { get; private set; }
46    protected List<Event> WhenChangeQueue { get; private set; }
47
48    public PriorityStore(Simulation environment, int capacity = int.MaxValue) {
49      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
50      Environment = environment;
51      Capacity = capacity;
52      PutQueue = new Queue<StorePut>();
53      GetQueue = new Queue<StoreGet>();
54      Items = new SimplePriorityQueue<object, double>();
55      WhenNewQueue = new List<Event>();
56      WhenAnyQueue = new List<Event>();
57      WhenFullQueue = new List<Event>();
58      WhenEmptyQueue = new List<Event>();
59      WhenChangeQueue = new List<Event>();
60    }
61    public PriorityStore(Simulation environment, IEnumerable<object> items, IEnumerable<double> priorities, int capacity = int.MaxValue) {
62      if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
63      Environment = environment;
64      Capacity = capacity;
65      PutQueue = new Queue<StorePut>();
66      GetQueue = new Queue<StoreGet>();
67      Items = new SimplePriorityQueue<object, double>();
68      var itemsList = items.ToList();
69      foreach (var zip in itemsList.Zip(priorities, (a, b) => new { Item = a, Prio = b }))
70        Items.Enqueue(zip.Item, zip.Prio);
71      if (Items.Count != itemsList.Count) throw new ArgumentException("Fewer priorities than items are given.", "priorities");
72
73      WhenNewQueue = new List<Event>();
74      WhenAnyQueue = new List<Event>();
75      WhenFullQueue = new List<Event>();
76      WhenEmptyQueue = new List<Event>();
77      WhenChangeQueue = new List<Event>();
78      if (capacity < Items.Count) throw new ArgumentException("There are more initial items than there is capacity.", "items");
79    }
80
81    public virtual StorePut Put(object item, double priority = 1) {
82      var put = new StorePut(Environment, TriggerGet, new PriorityItem(priority, item));
83      PutQueue.Enqueue(put);
84      TriggerPut();
85      return put;
86    }
87
88    public virtual StoreGet Get() {
89      var get = new StoreGet(Environment, TriggerPut);
90      GetQueue.Enqueue(get);
91      TriggerGet();
92      return get;
93    }
94
95    public virtual Event WhenNew() {
96      var whenNew = new Event(Environment);
97      WhenNewQueue.Add(whenNew);
98      return whenNew;
99    }
100
101    public virtual Event WhenAny() {
102      var whenAny = new Event(Environment);
103      WhenAnyQueue.Add(whenAny);
104      TriggerWhenAny();
105      return whenAny;
106    }
107
108    public virtual Event WhenFull() {
109      var whenFull = new Event(Environment);
110      WhenFullQueue.Add(whenFull);
111      TriggerWhenFull();
112      return whenFull;
113    }
114
115    public virtual Event WhenEmpty() {
116      var whenEmpty = new Event(Environment);
117      WhenEmptyQueue.Add(whenEmpty);
118      TriggerWhenEmpty();
119      return whenEmpty;
120    }
121
122    public virtual Event WhenChange() {
123      var whenChange = new Event(Environment);
124      WhenChangeQueue.Add(whenChange);
125      return whenChange;
126    }
127
128    protected virtual void DoPut(StorePut put) {
129      if (Items.Count < Capacity) {
130        var pi = (PriorityItem)put.Value;
131        Items.Enqueue(pi.Item, pi.Priority);
132        put.Succeed();
133      }
134    }
135
136    protected virtual void DoGet(StoreGet get) {
137      if (Items.Count > 0) {
138        var item = Items.Dequeue();
139        get.Succeed(item);
140      }
141    }
142
143    protected virtual void TriggerPut(Event @event = null) {
144      while (PutQueue.Count > 0) {
145        var put = PutQueue.Peek();
146        DoPut(put);
147        if (put.IsTriggered) {
148          PutQueue.Dequeue();
149          TriggerWhenNew();
150          TriggerWhenAny();
151          TriggerWhenFull();
152          TriggerWhenChange();
153        } else break;
154      }
155    }
156
157    protected virtual void TriggerGet(Event @event = null) {
158      while (GetQueue.Count > 0) {
159        var get = GetQueue.Peek();
160        DoGet(get);
161        if (get.IsTriggered) {
162          GetQueue.Dequeue();
163          TriggerWhenEmpty();
164          TriggerWhenChange();
165        } else break;
166      }
167    }
168
169    protected virtual void TriggerWhenNew() {
170      if (WhenNewQueue.Count == 0) return;
171      foreach (var evt in WhenNewQueue)
172        evt.Succeed();
173      WhenNewQueue.Clear();
174    }
175
176    protected virtual void TriggerWhenAny() {
177      if (Items.Count > 0) {
178        if (WhenAnyQueue.Count == 0) return;
179        foreach (var evt in WhenAnyQueue)
180          evt.Succeed();
181        WhenAnyQueue.Clear();
182      }
183    }
184
185    protected virtual void TriggerWhenFull() {
186      if (Count == Capacity) {
187        if (WhenFullQueue.Count == 0) return;
188        foreach (var evt in WhenFullQueue)
189          evt.Succeed();
190        WhenFullQueue.Clear();
191      }
192    }
193
194    protected virtual void TriggerWhenEmpty() {
195      if (Count == 0) {
196        if (WhenEmptyQueue.Count == 0) return;
197        foreach (var evt in WhenEmptyQueue)
198          evt.Succeed();
199        WhenEmptyQueue.Clear();
200      }
201    }
202
203    protected virtual void TriggerWhenChange() {
204      if (WhenChangeQueue.Count == 0) return;
205      foreach (var evt in WhenChangeQueue)
206        evt.Succeed();
207      WhenChangeQueue.Clear();
208    }
209
210    protected class PriorityItem {
211      public double Priority { get; protected set; }
212      public object Item { get; protected set; }
213
214      public PriorityItem(double priority, object item) {
215        Priority = priority;
216        Item = item;
217      }
218    }
219  }
220}
Note: See TracBrowser for help on using the repository browser.