using System;
using System.Threading;
namespace TokenBucketLib
{
/// 令牌桶
public class TokenBucket : IDisposable
{
#region 公开属性
///
/// 令牌投入速率
///
public int IR { get; set; }
private int _BS;
///
/// 令牌上限
///
public int BS
{
get
{
return _BS;
}
set
{
_BS = value;
if (CurCount > value)
{
CurCount = value;
}
}
}
///
/// 令牌桶是否在运行
///
public bool Runing { get; set; }
///
/// 当前剩余令牌数
///
public int CurCount { get; private set; }
#endregion
#region 私有字段
///
/// 添加令牌的计时器
///
private Timer timer;
///
/// 共享锁
///
protected static readonly object lockkey = new object();
#endregion
#region 事件
///
/// 添加令牌完成事件
///
public event Action Put;
#endregion
#region 构造
///
/// 默认构造,速率100,上限1000
///
public TokenBucket()
: this(100, 1000, 1000)
{
}
///
/// 通过指定速率和上限构造令牌桶
///
/// 投入速率
/// 令牌上限
/// 初始令牌数量
public TokenBucket(int ir, int bs, int ip)
{
IR = ir; BS = bs; CurCount = ip;
Runing = false;
}
#endregion
#region 公开方法
///
/// 令牌桶开始工作
///
public virtual void Start()
{
try
{
timer = new Timer(PutToken, null, 1000, 1000);
Runing = true;
}
catch (Exception ex)
{
Runing = false;
throw new Exception("TokenBucket start err!", ex);
}
}
///
/// 令牌桶停止工作
///
public virtual void Stop()
{
if (timer != null)
{
timer.Dispose();
timer = null;
}
Runing = false;
}
///
/// 设置令牌桶满令牌
///
public void SetFullPass()
{
CurCount = BS;
}
///
/// 清空令牌桶
///
public void ClearPass()
{
CurCount = 0;
}
///
/// 获得一块令牌
///
///
public virtual TokenBucketPass GetToken()
{
TokenBucketPass tbr = new TokenBucketPass();
if (!Runing)
{
tbr.State = TokenBucketPassEnum.TokenBucketNotRun;
}
else
{
lock (lockkey)
{
//Console.WriteLine("s");
//Console.WriteLine(CurCount);
if (CurCount <= 0)
{
tbr.State = TokenBucketPassEnum.unpassed;
}
else
{
CurCount--;
tbr.State = TokenBucketPassEnum.passed;
}
//Console.WriteLine("e");
}
}
return tbr;
}
#endregion
#region 私有方法
///
/// 向令牌桶添加令牌
///
///
protected void PutToken(object obj)
{
if (BS == CurCount) return;
lock (lockkey)
{
CurCount += IR;
if (CurCount > BS)
{
CurCount = BS;
}
}
if (Put != null) Put(this);
}
#endregion
#region IDisposable 成员
private bool IsDisposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!IsDisposed)
{
//释放托管资源
if (disposing)
{
if (timer != null)
{
timer.Dispose();
timer = null;
}
}
//释放非托管资源
}
IsDisposed = true;
}
~TokenBucket()
{
Dispose(false);
}
#endregion
}
}