#region License Information
/* SimSharp - A .NET port of SimPy, discrete event simulation framework
Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
namespace SimSharp {
public class Container {
public double Level { get; protected set; }
public double Capacity { get; protected set; }
protected Environment Environment { get; private set; }
protected Queue PutQueue { get; private set; }
protected Queue GetQueue { get; private set; }
public Container(Environment environment, double capacity = double.MaxValue, double initial = 0) {
if (capacity <= 0) throw new ArgumentException("Capacity must be > 0", "capacity");
if (initial < 0) throw new ArgumentException("Initial must be >= 0", "initial");
if (initial > capacity) throw new ArgumentException("Initial must be <= capacity", "initial");
Environment = environment;
Capacity = capacity;
Level = initial;
PutQueue = new Queue();
GetQueue = new Queue();
}
public virtual ContainerPut Put(double amount) {
if (amount > Capacity) throw new ArgumentException("Cannot put more than capacity", "amount");
var put = new ContainerPut(Environment, TriggerGet, amount);
PutQueue.Enqueue(put);
TriggerPut();
return put;
}
public virtual ContainerGet Get(double amount) {
if (amount > Capacity) throw new ArgumentException("Cannot get more than capacity", "amount");
var get = new ContainerGet(Environment, TriggerPut, amount);
GetQueue.Enqueue(get);
TriggerGet();
return get;
}
protected virtual void DoPut(ContainerPut put) {
if (Capacity - Level >= put.Amount) {
Level += put.Amount;
put.Succeed();
}
}
protected virtual void DoGet(ContainerGet get) {
if (Level >= get.Amount) {
Level -= get.Amount;
get.Succeed();
}
}
protected virtual void TriggerPut(Event @event = null) {
while (PutQueue.Count > 0) {
var put = PutQueue.Peek();
DoPut(put);
if (put.IsTriggered) {
PutQueue.Dequeue();
} else break;
}
}
protected virtual void TriggerGet(Event @event = null) {
while (GetQueue.Count > 0) {
var get = GetQueue.Peek();
DoGet(get);
if (get.IsTriggered) {
GetQueue.Dequeue();
} else break;
}
}
}
}