/// <summary> /// ThrottleBehavior constructor /// </summary> /// <param name="maxRequestPerSecond">Maximum number of operations per second</param> /// <param name="measurePeriodMs">Measure period to estimate current number of operations</param> public ThrottleBehavior(double maxRequestPerSecond, int measurePeriodMs) { if (maxRequestPerSecond <= 0) { throw new ArgumentOutOfRangeException(nameof(maxRequestPerSecond), nameof(maxRequestPerSecond) + " should be positive"); } if (measurePeriodMs <= 50) { throw new ArgumentOutOfRangeException(nameof(measurePeriodMs), nameof(measurePeriodMs) + " should be grater than 50"); } _measurePeriod = measurePeriodMs; _maxRequestPerSecond = maxRequestPerSecond; _lastTimeMeasure = GetTimeMeasureInMs(); _hitCount = 0; _syncObj = new object(); var tmpHit = Math.Ceiling(measurePeriodMs * maxRequestPerSecond / 1000.0); if (tmpHit < int.MaxValue) { _maxHitPerMeasure = (int)tmpHit; } else { _maxHitPerMeasure = int.MaxValue; } TurboContract.Assert(_maxHitPerMeasure > 0, conditionString: "_maxHitPerMeasure > 0"); }
/// <summary> /// Add subscription to the current delegate /// </summary> /// <param name="reference">New subscriber</param> public void Add(T reference) { if (reference == null) { return; } TurboContract.Assert(reference is Delegate, conditionString: "reference is Delegate"); if (reference is MulticastDelegate) { var invList = (reference as MulticastDelegate).GetInvocationList(); lock (_locker) { for (int i = 0; i < invList.Length; i++) { var weakEventReference = new WeakDelegate(invList[i]); _handlers.Add(weakEventReference); } } } else { lock (_locker) { var weakEventReference = new WeakDelegate(reference as Delegate); _handlers.Add(weakEventReference); } } }
/// <summary> /// Builds the strongly referenced delegate from the current weak delegate /// </summary> /// <returns>Constructed delegate</returns> public T GetDelegate() { Delegate result = null; lock (_locker) { for (int i = 0; i < _handlers.Count; i++) { TurboContract.Assert(_handlers[i] != null, conditionString: "_handlers[i] != null"); var newDeleg = _handlers[i].GetDelegate(); if (newDeleg != null) { result = Delegate.Combine(result, newDeleg); } else { _handlers.RemoveAt(i); i--; } } } return(result as T); }
/// <summary> /// Remove subscription from the current delegate /// </summary> /// <param name="reference">Subscriber that will be removed</param> public void Remove(T reference) { if (reference == null) { return; } TurboContract.Assert(reference is Delegate, conditionString: "reference is Delegate"); if (reference is MulticastDelegate) { var invList = (reference as MulticastDelegate).GetInvocationList(); lock (_locker) { int index = _handlers.FindIndex(x => Array.IndexOf(invList, x.GetDelegate()) >= 0); if (index >= 0) { _handlers.RemoveAt(index); } _handlers.RemoveAll(x => !x.IsActive); } } else { lock (_locker) { int index = _handlers.FindIndex(x => reference.Equals(x.GetDelegate())); if (index >= 0) { _handlers.RemoveAt(index); } _handlers.RemoveAll(x => !x.IsActive); } } }
private void Invariant() { TurboContract.Invariant(_valueStorage != null || _staticDelegateStorage != null); TurboContract.Invariant(_delegateType != null); TurboContract.Invariant(_methodInfo != null); }
/// <summary> /// Creates unlimited ThrottleBehavior (allow all operations) /// </summary> /// <returns>Created ThrottleBehavior</returns> public static ThrottleBehavior CreateNotLimited() { TurboContract.Ensures(TurboContract.Result <ThrottleBehavior>() != null); return(new ThrottleBehavior(int.MaxValue, 1000)); }
/// <summary> /// Calls when operation should be skipped (op/s exeeded) /// </summary> /// <param name="restTimeMs">Time in milliseconds till the end of the current measure period</param> protected virtual void OnThrottle(int restTimeMs) { TurboContract.Requires(restTimeMs >= 0, conditionString: "restTimeMs >= 0"); }