Python和Cython的无锁环形缓冲区。
ringbuf的Python项目详细描述
林布夫
为Python和Cython提供了一个无锁、单生产者、单用户的环形缓冲区。在
安装
苹果操作系统:brew install boost
Ubuntu:apt-get install libboost-all-dev
Windows:安装最新版本的^{BOOST_ROOT
环境变量指向其文件夹。在
然后:
pip install ringbuf
动机
在Python中使用实时DSP时,我们可能会封装一些外部C/C++库(例如PortAudio),它实时运行一些用户提供的回调函数。回调函数不应该分配/释放内存,不应该包含任何关键部分(互斥锁)等等,以防止优先级反转。如果回调包含Python对象,那么我们可能会分配和释放GIL,至少,获取和释放GIL。因此,如果我们期望实时性能,回调就不能与Python对象交互。因此,有必要在C/C++回调和Python之间以非锁定方式缓冲数据。在
为^{
使用
任何支持buffer protocol的Python对象都可以存储在ringbuf.RingBuffer
中。这包括但不限于:bytes
,bytearray
,array.array
,和{
纽比
^{pr2}$字节
fromringbufimportRingBufferbuffer=RingBuffer(format='B',capacity=11)buffer.push(b'hello world')popped=buffer.pop(11)assertbytes(popped)==b'hello world'
与C/C++ +EH3>接口
在我的模块.pxd公司名称:
# distutils: language = c++cdefvoidcallback(void*q)
在我的模块.pyx公司名称:
# distutils: language = c++fromarrayimportarrayfromringbuf.boostcimportspsc_queue,void_ptr_to_spsc_queue_char_ptrfromringbuf.ringbufcimportRingBufferfromsome_c_librarycimportsome_c_functioncdefvoidcallback(void*q):cdef:# Cast the void* back to an spsc_queue.# The underlying queue always holds chars.spsc_queue[char]*queue=void_ptr_to_spsc_queue_char_ptr(q)double[5]to_push=[1.0,2.0,3.0,4.0,5.0]# Since the queue holds chars, you'll have to cast and adjust size accordingly.queue.push(<char*>to_push,sizeof(double)*5)defdo_stuff():cdef:RingBufferbuffer=RingBuffer(format='d',capacity=100)void*queue=buffer.queue_void_ptr()# Pass our callback and a void pointer to the buffer's queue to some third party library.# Presumably, the C library schedules the callback and passes it the queue's void pointer.some_c_function(callback,queue)sleep(1)assertarray.array('d',buffer.pop(5))==array.array('d',range(1,6))
处理溢出和下溢
当RingBuffer.push()
溢出时,它返回无法推送的数据(如果全部被推送,则返回无):
fromringbufimportRingBufferbuffer=RingBuffer(format='B',capacity=10)overflowed=buffer.push(b'spam eggs ham')assertoverflowed==b'ham'
当RingBuffer.pop()
下溢时,它返回可能弹出的任何数据:
fromringbufimportRingBufferbuffer=RingBuffer(format='B',capacity=13)buffer.push(b'spam eggs ham')popped=buffer.pop(buffer.capacity*100)assertbytes(popped)==b'spam eggs ham'
有关其他用法,请参阅tests。在
支持的平台
Travis CI测试采用以下配置:
- Ubuntu 18.04仿生海狸:
- CPython3.6版
- CPython3.7版
- CPython3.8版
- PyPy7.3.0(3.6.9)
- 苹果操作系统:
- CPython3.6版
- CPython3.7版
- CPython3.8版
- PyPy7.3.0(3.6.9)
贡献
欢迎拉取请求,请将遇到的任何问题归档。在
变更日志
v2.5.0 2020年4月17日
- 增加了对Windows的实验支持。在
v2.4.0 2020-03-23
- 添加了
RingBuffer.reset()
方法来清除缓冲区。在
v2.3.0 2020年3月22日
- 添加了
concatenate
函数,用于连接多个支持缓冲区协议的任意Python对象。在
- 项目
标签: