TokenBucket/TokenBucketLib/QueueTokenBuket.cs
2019-04-25 17:03:09 +08:00

114 lines
3.6 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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