Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.SimSharp/3.1.1/SimSharp-3.1.1/Core/Resources/FilterStore.cs @ 17053

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

#2975: merged to stable

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