Skip to content
Merged

docs #239

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions BitFaster.Caching/BitOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@

namespace BitFaster.Caching
{
/// <summary>
/// Provides utility methods for bit-twiddling operations.
/// </summary>
public class BitOps
{
/// <summary>
/// Calculate the smallest power of 2 greater than the input parameter.
/// </summary>
/// <param name="x">The input parameter.</param>
/// <returns>Smallest power of two greater than or equal to x.</returns>
public static int CeilingPowerOfTwo(int x)
{
return (int)CeilingPowerOfTwo((uint)x);
}

/// <summary>
/// Calculate the smallest power of 2 greater than the input parameter.
/// </summary>
/// <param name="x">The input parameter.</param>
/// <returns>Smallest power of two greater than or equal to x.</returns>
public static uint CeilingPowerOfTwo(uint x)
{
#if NETSTANDARD2_0
Expand All @@ -26,11 +39,21 @@ public static uint CeilingPowerOfTwo(uint x)

}

/// <summary>
/// Counts the number of 1 bits in the input parameter.
/// </summary>
/// <param name="x">The input parameter.</param>
/// <returns>The number of 1 bits.</returns>
public static int BitCount(int x)
{
return BitCount((uint)x);
}

/// <summary>
/// Counts the number of 1 bits in the input parameter.
/// </summary>
/// <param name="x">The input parameter.</param>
/// <returns>The number of 1 bits.</returns>
public static int BitCount(uint x)
{
#if NETSTANDARD2_0
Expand All @@ -47,11 +70,21 @@ public static int BitCount(uint x)
#endif
}

/// <summary>
/// Counts the number of 1 bits in the input parameter.
/// </summary>
/// <param name="x">The input parameter.</param>
/// <returns>The number of 1 bits.</returns>
public static int BitCount(long x)
{
return BitCount((ulong)x);
}

/// <summary>
/// Counts the number of 1 bits in the input parameter.
/// </summary>
/// <param name="x">The input parameter.</param>
/// <returns>The number of 1 bits.</returns>
public static int BitCount(ulong x)
{
#if NETSTANDARD2_0
Expand All @@ -68,8 +101,14 @@ public static int BitCount(ulong x)
#endif
}

// Computes Stafford variant 13 of 64-bit mix function.
// http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
/// <summary>
/// Computes Stafford variant 13 of 64-bit mix function.
/// </summary>
/// <param name="z">The input parameter.</param>
/// <returns>A bit mix of the input parameter.</returns>
/// <remarks>
/// See http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
/// </remarks>
public static ulong Mix64(ulong z)
{
z = (z ^ z >> 30) * 0xbf58476d1ce4e5b9L;
Expand Down
28 changes: 27 additions & 1 deletion BitFaster.Caching/Buffers/MpmcBoundedBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public sealed class MpmcBoundedBuffer<T>
private readonly int slotsMask;
private PaddedHeadAndTail headAndTail; // mutable struct, don't mark readonly

/// <summary>
/// Initializes a new instance of the MpmcBoundedBuffer class with the specified bounded capacity.
/// </summary>
/// <param name="boundedLength">The bounded length.</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public MpmcBoundedBuffer(int boundedLength)
{
if (boundedLength < 0)
Expand Down Expand Up @@ -54,6 +59,9 @@ public MpmcBoundedBuffer(int boundedLength)
}
}

/// <summary>
/// Gets the number of items contained in the buffer.
/// </summary>
public int Count
{
get
Expand Down Expand Up @@ -87,8 +95,16 @@ private int GetCount(int head, int tail)
return 0;
}

/// <summary>
/// The bounded capacity.
/// </summary>
public int Capacity => slots.Length;

/// <summary>
/// Tries to remove an item.
/// </summary>
/// <param name="item">The item to be removed.</param>
/// <returns>A BufferStatus value indicating whether the operation succeeded.</returns>
public BufferStatus TryTake(out T item)
{
// Get the head at which to try to dequeue.
Expand Down Expand Up @@ -145,6 +161,11 @@ public BufferStatus TryTake(out T item)
return BufferStatus.Contended;
}

/// <summary>
/// Tries to add the specified item.
/// </summary>
/// <param name="item">The item to be added.</param>
/// <returns>A BufferStatus value indicating whether the operation succeeded.</returns>
public BufferStatus TryAdd(T item)
{
// Get the tail at which to try to return.
Expand Down Expand Up @@ -189,7 +210,12 @@ public BufferStatus TryAdd(T item)
return BufferStatus.Contended;
}

// Not thread safe
/// <summary>
/// Removes all values from the buffer.
/// </summary>
/// <remarks>
/// Not thread safe.
/// </remarks>
public void Clear()
{
slots = new Slot[slots.Length];
Expand Down
46 changes: 42 additions & 4 deletions BitFaster.Caching/Buffers/MpscBoundedBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public sealed class MpscBoundedBuffer<T> where T : class
private readonly int mask;
private PaddedHeadAndTail headAndTail; // mutable struct, don't mark readonly

/// <summary>
/// Initializes a new instance of the MpscBoundedBuffer class with the specified bounded capacity.
/// </summary>
/// <param name="boundedLength">The bounded length.</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public MpscBoundedBuffer(int boundedLength)
{
if (boundedLength < 0)
Expand All @@ -33,8 +38,14 @@ public MpscBoundedBuffer(int boundedLength)
mask = boundedLength - 1;
}

/// <summary>
/// The bounded capacity.
/// </summary>
public int Capacity => buffer.Length;

/// <summary>
/// Gets the number of items contained in the buffer.
/// </summary>
public int Count
{
get
Expand Down Expand Up @@ -68,7 +79,14 @@ private int GetCount(int head, int tail)
return 0;
}

// thread safe
/// <summary>
/// Tries to add the specified item.
/// </summary>
/// <param name="item">The item to be added.</param>
/// <returns>A BufferStatus value indicating whether the operation succeeded.</returns>
/// <remarks>
/// Thread safe.
/// </remarks>
public BufferStatus TryAdd(T item)
{
int head = Volatile.Read(ref headAndTail.Head);
Expand All @@ -91,7 +109,15 @@ public BufferStatus TryAdd(T item)
return BufferStatus.Contended;
}

// thread safe for single try take/drain + multiple try add

/// <summary>
/// Tries to remove an item.
/// </summary>
/// <param name="item">The item to be removed.</param>
/// <returns>A BufferStatus value indicating whether the operation succeeded.</returns>
/// <remarks>
/// Thread safe for single try take/drain + multiple try add.
/// </remarks>
public BufferStatus TryTake(out T item)
{
int head = Volatile.Read(ref headAndTail.Head);
Expand Down Expand Up @@ -119,7 +145,14 @@ public BufferStatus TryTake(out T item)
return BufferStatus.Success;
}

// thread safe for single try take/drain + multiple try add
/// <summary>
/// Drains the buffer into the specified array segment.
/// </summary>
/// <param name="output">The output buffer</param>
/// <returns>The number of items written to the output buffer.</returns>
/// <remarks>
/// Thread safe for single try take/drain + multiple try add.
/// </remarks>
public int DrainTo(ArraySegment<T> output)
{
int head = Volatile.Read(ref headAndTail.Head);
Expand Down Expand Up @@ -156,7 +189,12 @@ public int DrainTo(ArraySegment<T> output)
return outCount;
}

// Not thread safe
/// <summary>
/// Removes all values from the buffer.
/// </summary>
/// <remarks>
/// Not thread safe.
/// </remarks>
public void Clear()
{
buffer = new T[buffer.Length];
Expand Down
34 changes: 34 additions & 0 deletions BitFaster.Caching/Buffers/StripedMpmcBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,20 @@ public sealed class StripedMpmcBuffer<T>

private MpmcBoundedBuffer<T>[] buffers;

/// <summary>
/// Initializes a new instance of the StripedMpmcBuffer class with the specified stripe count and buffer size.
/// </summary>
/// <param name="stripeCount">The stripe count.</param>
/// <param name="bufferSize">The buffer size.</param>
public StripedMpmcBuffer(int stripeCount, int bufferSize)
: this(new StripedBufferSize(bufferSize, stripeCount))
{
}

/// <summary>
/// Initializes a new instance of the StripedMpmcBuffer class with the specified buffer size.
/// </summary>
/// <param name="bufferSize">The buffer size.</param>
public StripedMpmcBuffer(StripedBufferSize bufferSize)
{
buffers = new MpmcBoundedBuffer<T>[bufferSize.StripeCount];
Expand All @@ -29,8 +38,19 @@ public StripedMpmcBuffer(StripedBufferSize bufferSize)
}
}

/// <summary>
/// The bounded capacity.
/// </summary>
public int Capacity => buffers.Length * buffers[0].Capacity;

/// <summary>
/// Drains the buffer into the specified output buffer.
/// </summary>
/// <param name="outputBuffer">The output buffer</param>
/// <returns>The number of items written to the output buffer.</returns>
/// <remarks>
/// Thread safe.
/// </remarks>
public int DrainTo(T[] outputBuffer)
{
var count = 0;
Expand All @@ -53,6 +73,14 @@ public int DrainTo(T[] outputBuffer)
return count;
}

/// <summary>
/// Tries to add the specified item.
/// </summary>
/// <param name="item">The item to be added.</param>
/// <returns>A BufferStatus value indicating whether the operation succeeded.</returns>
/// <remarks>
/// Thread safe.
/// </remarks>
public BufferStatus TryAdd(T item)
{
var z = BitOps.Mix64((ulong)Environment.CurrentManagedThreadId);
Expand All @@ -78,6 +106,12 @@ public BufferStatus TryAdd(T item)
return result;
}

/// <summary>
/// Removes all values from the buffer.
/// </summary>
/// <remarks>
/// Not thread safe.
/// </remarks>
public void Clear()
{
for (var i = 0; i < buffers.Length; i++)
Expand Down
39 changes: 38 additions & 1 deletion BitFaster.Caching/Buffers/StripedMpscBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,22 @@ public sealed class StripedMpscBuffer<T> where T : class
{
const int MaxAttempts = 3;

private MpscBoundedBuffer<T>[] buffers;
private readonly MpscBoundedBuffer<T>[] buffers;

/// <summary>
/// Initializes a new instance of the StripedMpscBuffer class with the specified stripe count and buffer size.
/// </summary>
/// <param name="stripeCount">The stripe count.</param>
/// <param name="bufferSize">The buffer size.</param>
public StripedMpscBuffer(int stripeCount, int bufferSize)
: this(new StripedBufferSize(bufferSize, stripeCount))
{
}

/// <summary>
/// Initializes a new instance of the StripedMpscBuffer class with the specified buffer size.
/// </summary>
/// <param name="bufferSize">The buffer size.</param>
public StripedMpscBuffer(StripedBufferSize bufferSize)
{
buffers = new MpscBoundedBuffer<T>[bufferSize.StripeCount];
Expand All @@ -32,10 +41,24 @@ public StripedMpscBuffer(StripedBufferSize bufferSize)
}
}

/// <summary>
/// Gets the number of items contained in the buffer.
/// </summary>
public int Count => buffers.Sum(b => b.Count);

/// <summary>
/// The bounded capacity.
/// </summary>
public int Capacity => buffers.Length * buffers[0].Capacity;

/// <summary>
/// Drains the buffer into the specified array segment.
/// </summary>
/// <param name="outputBuffer">The output buffer</param>
/// <returns>The number of items written to the output buffer.</returns>
/// <remarks>
/// Thread safe for single try take/drain + multiple try add.
/// </remarks>
public int DrainTo(T[] outputBuffer)
{
var count = 0;
Expand All @@ -54,6 +77,14 @@ public int DrainTo(T[] outputBuffer)
return count;
}

/// <summary>
/// Tries to add the specified item.
/// </summary>
/// <param name="item">The item to be added.</param>
/// <returns>A BufferStatus value indicating whether the operation succeeded.</returns>
/// <remarks>
/// Thread safe.
/// </remarks>
public BufferStatus TryAdd(T item)
{
var z = BitOps.Mix64((ulong)Environment.CurrentManagedThreadId);
Expand All @@ -79,6 +110,12 @@ public BufferStatus TryAdd(T item)
return result;
}

/// <summary>
/// Removes all values from the buffer.
/// </summary>
/// <remarks>
/// Not thread safe.
/// </remarks>
public void Clear()
{
for (var i = 0; i < buffers.Length; i++)
Expand Down
Loading