114 lines
3.6 KiB
C#
114 lines
3.6 KiB
C#
|
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
|
|||
|
|
|||
|
}
|
|||
|
}
|