How to make an Action run only X count of times in C#?

// Copyright © Protiguous. All Rights Reserved.
//
// This entire copyright notice and license must be retained and must be kept visible in any binaries, libraries,
// repositories, or source code (directly or derived) from our binaries, libraries, projects, solutions, or applications.
//
// All source code belongs to [email protected] unless otherwise specified or the original license has
// been overwritten by formatting. (We try to avoid it from happening, but it does accidentally happen.)
//
// Any unmodified portions of source code gleaned from other sources still retain their original license and our thanks goes to those Authors.
// If you find your code unattributed in this source code, please let us know so we can properly attribute you and include the proper licenses and/or copyrights.
// If you want to use any of our code in a commercial project, you must contact [email protected] for permission, license, and a quote.
//
// Donations, payments, and royalties are accepted via bitcoin: 1Mad8TxTqxKnMiHuZxArFvX8BuFEB9nqX2 and PayPal: [email protected]
//
// ====================================================================
// Disclaimer:  Usage of the source code or binaries is AS-IS.
// No warranties are expressed, implied, or given.
// We are NOT responsible for Anything You Do With Our Code.
// We are NOT responsible for Anything You Do With Our Executables.
// We are NOT responsible for Anything You Do With Your Computer.
// ====================================================================
//
// Contact us by email if you have any questions, helpful criticism, or if you would like to use our code in your project(s).
// For business inquiries, please contact me at [email protected]
// Our software can be found at "https://Protiguous.com/Software/"
// Our GitHub address is "https://github.com/Protiguous".
//
// File "DelegateExtensions.cs" last formatted on 2022-04-07 at 12:38 PM by Protiguous.

public static class DelegateExtensions {

	private sealed class ContextCallOnlyXTimes {
		internal Int64 CallsAllowed;

		public ContextCallOnlyXTimes( Int64 times ) {
			if ( times <= 0 ) {
				times = 0;
			}
			this.CallsAllowed = times;
		}
	}

	/// <summary>Only allow a delegate to run X times.</summary>
	/// <param name="action"></param>
	/// <param name="callsAllowed"></param>
	/// <example>var barWithBarrier = ActionBarrier(Bar, remainingCallsAllowed: 2 );</example>
	/// <remarks>Calling the delegate more often than <paramref name="callsAllowed" /> should just NOP.</remarks>
	public static Action ActionBarrier( this Action action, Int64 callsAllowed = 1 ) {
		var context = new ContextCallOnlyXTimes( callsAllowed );

		return () => {
			if ( Interlocked.Decrement( ref context.CallsAllowed ) >= 1 ) {
				action();
			}
		};
	}

	/// <summary>Only allow a delegate to run X times.</summary>
	/// <param name="action"></param>
	/// <param name="parameter"></param>
	/// <param name="callsAllowed"></param>
	/// <example>var barWithBarrier = ActionBarrier(Bar, remainingCallsAllowed: 2 );</example>
	/// <remarks>Calling the delegate more often than <paramref name="callsAllowed" /> should just NOP.</remarks>
	public static Action ActionBarrier<T>( this Action<T?> action, T? parameter, Int64 callsAllowed = 1 ) {
		var context = new ContextCallOnlyXTimes( callsAllowed );

		return () => {
			if ( Interlocked.Decrement( ref context.CallsAllowed ) >= 1 ) {
				action( parameter );
			}
		};
	}
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s