Skip to content

Instantly share code, notes, and snippets.

@mebjas
Created September 17, 2018 04:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mebjas/222d76dbb51250c938d83331720bd469 to your computer and use it in GitHub Desktop.
Save mebjas/222d76dbb51250c938d83331720bd469 to your computer and use it in GitHub Desktop.
/// <summary>
/// Semaphore Class with variable concurrency
/// </summary>
public class SemaphoreFat : IDisposable
{
/// <summary>
/// Maximum capacity of this semaphore
/// </summary>
private int maxCapacity;
/// <summary>
/// Current capacity of this semaphore
/// </summary>
private int capacity;
/// <summary>
/// internal semaphore object instance
/// </summary>
private SemaphoreSlim sem;
/// <summary>
/// Initializes a new instance of the <see cref="SemaphoreFat" /> class.
/// </summary>
/// <param name="initialCapacity"></param>
/// <param name="maxCapacity"></param>
public SemaphoreFat(int initialCapacity, int maxCapacity)
{
if (capacity > maxCapacity)
{
throw new InvalidOperationException("Capacity cannot be greater than Max");
}
this.maxCapacity = maxCapacity;
this.capacity = initialCapacity;
this.sem = new SemaphoreSlim(this.maxCapacity);
this.updateHeldCapacity(this.capacity, this.maxCapacity);
}
/// <summary>
/// Blocks the current thread until it can enter the <see cref="SemaphoreFat"/>
/// </summary>
public void Wait()
{
this.sem.Wait();
}
/// <summary>
/// Releases the <see cref="SemaphoreFat"/> object once.
/// </summary>
public void Release()
{
this.sem.Release();
}
/// <summary>
/// Updates the capacity of the semaphore. If it's a capacity increase request
/// This thread shall be blocked until that happens
/// </summary>
/// <param name="newCapacity">new capacity of the semaphore</param>
public void Update(int newCapacity)
{
if (newCapacity <= 0)
{
throw new InvalidOperationException("Capacity cannot be less than or equal to zero;");
}
if (newCapacity > this.maxCapacity)
{
throw new InvalidOperationException("Capacity cannot be greater than or max capacity;");
}
this.updateHeldCapacity(newCapacity, this.capacity);
this.capacity = newCapacity;
}
/// <summary>
/// Disposes the object
/// </summary>
public void Dispose()
{
try
{
this.sem.Dispose();
}
catch
{
////
}
}
/// <summary>
/// Method to update the capacity of this semaphore
/// </summary>
/// <param name="newCapacity">new capacity requested</param>
/// <param name="oldCapacity">older capacity</param>
private void updateHeldCapacity(int newCapacity, int oldCapacity)
{
int delta = newCapacity - oldCapacity;
if (delta < 0)
{
for (int i = 0; i < -delta; i++)
{
this.sem.Wait();
}
}
else
{
for (int i = 0; i < delta; i++)
{
this.sem.Release();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment