Buffer cincin multi-produser tunggal-konsumen (MPSC) yang mendukung operasi jangkauan yang berdekatan dan yang dapat dengan mudah digunakan untuk menyampaikan pesan. Implementasi ditulis dalam C11 dan didistribusikan di bawah lisensi BSD 2-Clause.
int ringbuf_setup(ringbuf_t *rbuf, unsigned nworkers, size_t length)
rbuf adalah pointer ke objek buffer cincin buram; Penelepon bertanggung jawab untuk mengalokasikan ruang untuk objek ini. Biasanya, objek akan dialokasikan secara dinamis jika menggunakan utas atau dipesan dalam memori bersama diblokir jika menggunakan proses. Ukuran alokasi untuk objek harus diperoleh dengan menggunakan fungsi ringbuf_get_sizes . Mengembalikan 0 pada kesuksesan dan -1 pada kegagalan. void ringbuf_get_sizes(unsigned nworkers, size_t *ringbuf_obj_size, size_t *ringbuf_worker_size)
ringbuf_t buram dan, secara opsional, struktur ringbuf_worker_t . Ukuran struktur ringbuf_t tergantung pada jumlah pekerja, yang ditentukan oleh parameter nworkers . ringbuf_worker_t *ringbuf_register(ringbuf_t *rbuf, unsigned i)
i adalah nomor pekerja, mulai dari nol (yaitu harus lebih dari nworkers yang digunakan dalam pengaturan). Saat sukses, mengembalikan pointer ke ringbuf_worker_t terstruktur, yang merupakan bagian dari blok memori ringbuf_t . Kegagalan, kembali 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 harus dipanggil untuk menunjukkannya. Nested mendapatkan panggilan tidak diizinkan. void ringbuf_produce(ringbuf_t *rbuf, ringbuf_worker_t *worker)
size_t ringbuf_consume(ringbuf_t *rbuf, size_t *offset)
ringbuf_release harus dipanggil untuk menunjukkan itu. void ringbuf_release(ringbuf_t *rbuf, size_t nbytes)
Konsumen akan mengembalikan blok rentang yang diproduksi yang diproduksi yaitu panggilan ringbuf_consume tidak akan mengembalikan rentang parsial. Jika Anda menganggap jangkauan yang diproduksi sebagai pesan, maka konsumen akan mengembalikan blok pesan, selalu berakhir pada batas pesan. Perilaku seperti itu memungkinkan kita untuk menggunakan implementasi buffer cincin ini sebagai antrian pesan.
Implementasi diuji secara luas pada mesin X86 24-core, lihat tes tegangan untuk detail tentang teknik tersebut. Ini juga memberikan contoh bagaimana mekanisme dapat digunakan untuk lewat pesan.
Implementasi buffer cincin ini selalu menyediakan rentang ruang yang berdekatan untuk produser. Ini dicapai dengan pembungkus awal jika kisaran yang diminta tidak sesuai pada akhirnya. Implikasi dari ini adalah bahwa panggilan ringbuf_acquire mungkin gagal jika kisaran yang diminta lebih besar dari setengah dari ukuran buffer. Oleh karena itu, mungkin perlu untuk memastikan bahwa ukuran buffer cincin setidaknya dua kali lebih besar dari ukuran unit produksi maksimum.
Perlu juga dicatat bahwa salah satu pertukaran desain tersebut adalah bahwa konsumen saat ini melakukan pemindaian O (n) pada daftar produsen.
Produser:
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 );
}Konsumen:
if (( len = ringbuf_consume ( r , & off )) != 0 ) {
process ( & buf [ off ], len );
ringbuf_release ( r , len );
}