TokenBucket/TokenBucketLib/QueueTokenBuket.cs

114 lines
3.6 KiB
C#
Raw Normal View History

2019-04-25 17:03:09 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TokenBucketLib
{
/// <summary>
/// 队列令牌桶
/// 资源请求首先到达令牌桶,如果获得令牌马上返回,如果失败将进入等待队列,等待获得令牌后返回,或者令牌桶满后获取失败并丢弃。
/// </summary>
public class QueueTokenBucket : TokenBucket
{
/// <summary>
/// 最大缓冲对列数。-1为不限长度。
/// </summary>
public int QueueMaxLenth { get; set; }
private Queue<TokenBucketPass> queue;
private readonly static object objlock = new object();
/// <summary>
/// 构造一个带缓冲队列的令牌桶
/// </summary>
public QueueTokenBucket()
: this(-1)
{
}
/// <summary>
/// 通过提供最大缓冲队列数构造缓冲队列令牌桶
/// </summary>
/// <param name="queueMaxLenth">缓冲区大小。-1为不限制大小。</param>
public QueueTokenBucket(int queueMaxLenth)
{
QueueMaxLenth = queueMaxLenth;
queue = new Queue<TokenBucketPass>();
base.Put += new Action<TokenBucket>(QueueTokenBuket_Put);
}
private void QueueTokenBuket_Put(TokenBucket obj)
{
if (queue.Count > 0)
{
lock (objlock)
{
var c = queue.Count;
for (int i = 0; i < c; i++)
{
var r = base.GetToken();
if (r.State == TokenBucketPassEnum.passed)
{
TokenBucketPass result = queue.Dequeue();
result.State = TokenBucketPassEnum.passed;
if (GetTokenEnd != null) GetTokenEnd(this, new TokenBucketEventArgs(result));
}
else
{
break;
}
}
}
}
}
/// <summary>
///
/// </summary>
public event Action<QueueTokenBucket, TokenBucketEventArgs> GetTokenEnd;
/// <summary>
/// 开始异步获取令牌
/// </summary>
/// <param name="requester">异步传入的对象这个对象会随TokenBucketPass.Requester传出。</param>
public void GetTokenAsyn(object requester)
{
var result = new TokenBucketPass();
result.Requester = requester;
var r = base.GetToken();
if (r.State == TokenBucketPassEnum.passed)
{
result.State = r.State;
if (GetTokenEnd != null) GetTokenEnd(this, new TokenBucketEventArgs(result));
}
else
{
if (QueueMaxLenth != -1 && QueueMaxLenth < queue.Count)
{
result.State = TokenBucketPassEnum.losted;
GetTokenEnd(this, new TokenBucketEventArgs(result));
}
else
{
queue.Enqueue(result);
}
}
}
#region IDisposable
protected override void Dispose(bool disposing)
{
if (disposing)
{
queue.Clear();
}
base.Dispose(disposing);
}
#endregion
}
}