ロックフリーマルチプロデューサーシングル消費者(MPSC)リングバッファーは、連続した範囲操作をサポートし、メッセージの合格に便利に使用できる。実装はC11で記述され、2条件BSDライセンスの下で配布されます。
int ringbuf_setup(ringbuf_t *rbuf, unsigned nworkers, size_t length)
rbufは、不透明なリングバッファーオブジェクトへのポインターです。発信者は、このオブジェクトのスペースを割り当てる責任があります。通常、オブジェクトは、スレッドを使用している場合に動的に割り当てられたり、プロセスを使用している場合にブロックされた共有メモリに予約されます。オブジェクトの割り当てサイズは、 ringbuf_get_sizes関数を使用して取得するものとします。成功で0を返し、失敗に-1を返します。 void ringbuf_get_sizes(unsigned nworkers, size_t *ringbuf_obj_size, size_t *ringbuf_worker_size)
ringbuf_tのサイズと、オプションではringbuf_worker_t構造を返します。 ringbuf_t構造のサイズは、 nworkersパラメーターで指定された労働者の数に依存します。 ringbuf_worker_t *ringbuf_register(ringbuf_t *rbuf, unsigned i)
iゼロから始まる労働者番号です(つまり、セットアップで使用されているnworkersよりも)。成功すると、 ringbuf_tメモリブロックの一部である不透明なringbuf_worker_t structuredにポインターを返します。失敗すると、 NULLを返します。 void ringbuf_unregister(ringbuf_t *rbuf, ringbuf_worker_t *worker)
ssize_t ringbuf_acquire(ringbuf_t *rbuf, ringbuf_worker_t *worker, size_t len)
ringbuf_produce関数を呼び出す必要があります。ネストされた取得コールは許可されていません。 void ringbuf_produce(ringbuf_t *rbuf, ringbuf_worker_t *worker)
size_t ringbuf_consume(ringbuf_t *rbuf, size_t *offset)
ringbuf_release関数を呼び出す必要があります。 void ringbuf_release(ringbuf_t *rbuf, size_t nbytes)
消費者は、生成ringbuf_consumeれた範囲の連続したブロックを返します。生成された範囲をメッセージとして考えると、消費者はメッセージのブロックを返し、常にメッセージの境界で終わります。このような動作により、このリングバッファーの実装をメッセージキューとして使用できます。
この実装は、24コアX86マシンで広くテストされています。手法の詳細については、ストレステストを参照してください。また、メカニズムをメッセージの合格に使用する方法の例を提供します。
このリングバッファーの実装は、生産者に常に連続した範囲のスペースを提供します。要求された範囲が最終的に適合できない場合、初期のラップアラウンドによって達成されます。これの意味は、要求された範囲がバッファサイズの半分を超えると、 ringbuf_acquireコールが失敗する可能性があるということです。したがって、リングバッファーのサイズが最大生産ユニットサイズの少なくとも2倍の大きさであることを確認する必要がある場合があります。
また、そのような設計のトレードオフの1つは、消費者が現在生産者のリストでO(n)スキャンを実行していることであることに注意する必要があります。
プロデューサー:
if (( w = ringbuf_register ( r , worker_id )) == NULL )
err ( EXIT_FAILURE , "ringbuf_register" )
...
if (( off = ringbuf_acquire ( r , w , len )) != -1 ) {
memcpy ( & buf [ off ], payload , len );
ringbuf_produce ( r , tls );
}消費者:
if (( len = ringbuf_consume ( r , & off )) != 0 ) {
process ( & buf [ off ], len );
ringbuf_release ( r , len );
}