低レイテンシの C++ 同期キューが必要です。要件は次のとおりです。
- 実行時にメモリを割り当てません。新しいアイテムを memcpy したいだけです
- ロックフリー
- 一人の作家
- 複数のリーダー (並列)
- 並行読み書き
私はそれを自分で実装する必要がありますか、boost
それとも別の実装を共有できるものを使用できますか? メモリを割り当てたくないので、おそらくキューは内部でリングバッファを使用する必要があります。
以下は、私が書いたリングバッファですC#
。4 を除くすべての要件を満たしています。C++ に書き直すのは簡単ですが、この実装で複数のリーダーをサポートし、ロックを解除する方法がわかりません。
public sealed class ArrayPool<T> where T : class, new()
{
readonly T[] array;
private readonly uint length;
private readonly uint MASK;
private volatile uint curWriteNum;
private volatile uint curReadNum;
public ArrayPool(uint length = 65536) // length must be power of 2
{
if (length <= 0) throw new ArgumentOutOfRangeException("length");
array = new T[length];
for (int i = 0; i < length; i++)
{
array[i] = new T();
}
this.length = length;
MASK = length - 1;
}
public bool IsEmpty
{
get { return curReadNum == curWriteNum; }
}
/// <summary>
/// TryGet() itself is not thread safe and should be called from one thread.
/// However TryGet() and Obtain/Commit can be called from different threads
/// </summary>
/// <returns></returns>
public T TryGet()
{
if (curReadNum == curWriteNum)
{
return null;
}
T result = array[curReadNum & MASK];
curReadNum++;
return result;
}
public T Obtain()
{
return array[curWriteNum & MASK];
}
public void Commit()
{
curWriteNum++;
if (curWriteNum - curReadNum > length)
{
Log.Push(LogItemType.Error,
"ArrayPool curWriteNum - curReadNum > length: "
+ curWriteNum + ' ' + curReadNum + ' ' + length);
}
}
}
使い方は簡単です。最初に を呼び出しObtain
、次に項目を再構成してから を呼び出しますCommit
。
C#
必要なものを示すためだけに実装を追加します。「複数のリーダー」のサポートを追加し、同時に実装をロックフリーに保つことは不可能だと思うので、何か新しいものが必要です。