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
|
||
|
||
}
|
||
}
|