無鎖的多生產商單量消費者(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_worker_t結構化,這是ringbuf_t內存塊的一部分。失敗時,返回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調用可能會失敗。因此,可能有必要確保環緩衝區的大小至少是最大生產單元尺寸的兩倍。
還應注意的是,這種設計的權衡之一是,消費者目前在生產商列表中執行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 );
}