| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Diagnostics;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Diagnostics;
- using System.Collections.Generic;
- using System.Threading;
- using System.ServiceModel.Diagnostics.Application;
- sealed class FlowThrottle
- {
- int capacity;
- int count;
- bool warningIssued;
- int warningRestoreLimit;
- object mutex;
- WaitCallback release;
- Queue<object> waiters;
- String propertyName;
- String configName;
- Action acquired;
- Action released;
- Action<int> ratio;
- internal FlowThrottle(WaitCallback release, int capacity, String propertyName, String configName)
- {
- if (capacity <= 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxThrottleLimitMustBeGreaterThanZero0)));
- this.count = 0;
- this.capacity = capacity;
- this.mutex = new object();
- this.release = release;
- this.waiters = new Queue<object>();
- this.propertyName = propertyName;
- this.configName = configName;
- this.warningRestoreLimit = (int)Math.Floor(0.7 * (double)capacity);
- }
- internal int Capacity
- {
- get { return this.capacity; }
- set
- {
- if (value <= 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxThrottleLimitMustBeGreaterThanZero0)));
- this.capacity = value;
- }
- }
- internal bool Acquire(object o)
- {
- bool acquiredThrottle = true;
- lock (this.mutex)
- {
- if (this.count < this.capacity)
- {
- this.count++;
- }
- else
- {
- if (this.waiters.Count == 0)
- {
- if (TD.MessageThrottleExceededIsEnabled())
- {
- if (!this.warningIssued)
- {
- TD.MessageThrottleExceeded(this.propertyName, this.capacity);
- this.warningIssued = true;
- }
- }
- if (DiagnosticUtility.ShouldTraceWarning)
- {
- string traceMessage;
- if (this.propertyName != null)
- {
- traceMessage = SR.GetString(SR.TraceCodeServiceThrottleLimitReached,
- this.propertyName, this.capacity, this.configName);
- }
- else
- {
- traceMessage = SR.GetString(SR.TraceCodeServiceThrottleLimitReachedInternal,
- this.capacity);
- }
- TraceUtility.TraceEvent(
- TraceEventType.Warning, TraceCode.ServiceThrottleLimitReached, traceMessage);
- }
- }
- this.waiters.Enqueue(o);
- acquiredThrottle = false;
- }
- if (this.acquired != null)
- {
- this.acquired();
- }
- if (this.ratio != null)
- {
- this.ratio(this.count);
- }
- return acquiredThrottle;
- }
- }
- internal void Release()
- {
- object next = null;
- lock (this.mutex)
- {
- if (this.waiters.Count > 0)
- {
- next = this.waiters.Dequeue();
- if (this.waiters.Count == 0)
- this.waiters.TrimExcess();
- }
- else
- {
- this.count--;
- if (this.count < this.warningRestoreLimit)
- {
- if (TD.MessageThrottleAtSeventyPercentIsEnabled() && this.warningIssued)
- {
- TD.MessageThrottleAtSeventyPercent(this.propertyName, this.capacity);
- }
- this.warningIssued = false;
- }
- }
- }
- if (next != null)
- this.release(next);
- if (this.released != null)
- {
- this.released();
- }
- if (this.ratio != null)
- {
- this.ratio(this.count);
- }
- }
- internal void SetReleased(Action action)
- {
- this.released = action;
- }
- internal void SetAcquired(Action action)
- {
- this.acquired = action;
- }
- internal void SetRatio(Action<int> action)
- {
- this.ratio = action;
- }
- }
- }
|