2016-11-18 143 views
3

我不确定何时使用&mut self而不仅仅是&self在libzmq C API的Rust绑定中。有点背景:libzmq提供了socket的“对象”,它有一个类似于BSD套接字API的API,并用C中的不透明指针表示。这个指针实际上只是一个句柄,类似于POSIX文件描述符,并且C API被设计为使得它可能是而不是以获得对该指针后面的存储器的任何引用。什么时候应该在C库的Rust绑定中使用`&mut self`与`&self`?

在这些情况下,它是安全和良好的API设计公开套接字方法与不可变的self?作为一个具体的例子,考虑zmq_send()

int zmq_send (void *socket, void *buf, size_t len, int flags); 

我认为它可以(也应该)使用一成不变的自我暴露,即:

pub fn send(&self, data: &[u8], flags: i32) -> Result<()> { ... } 

然而,可比的防锈标准库的方法使用&mut self,例如std::io::Write::write(),如由std::net::TcpStream执行。另一方面,std::net::UdpStream::write()只需要&self。我的猜测是使用&mut self仅仅是因为它是Write特征的实现,反过来(我猜)使用&mut self来限制特征的实现。

我希望有人可以在这里备份或反驳我的猜测 - 我在本书或Nomicon中找不到有关该主题的任何具体内容。

+0

相关:[为什么可以实现Read对File的不可变引用?](http://stackoverflow.com/q/31503488/155423)。在这种情况下,操作系统处理底层文件描述符的多次使用,所以没有理由在Rust中执行该操作。 – Shepmaster

回答

5

在这种情况下,对象是否发生了变异是次要的;主要问题是“两个参考文献是否同时使用是安全的?”。两个线程可以同时在同一个对象上调用zmq_send(或其他方法),或者(如果API允许)通过嵌套的回调函数等等,可以吗?

如果不是,请使用&mut self并让Rust执行您所需的安全保证。

如果它是安全的,那么也许&self是适当的,如果zmq保证它没问题;这将如Mutex::lock&self

+0

我应该补充说,有问题的套接字选项不是线程安全的,但是如果绑定没有实现'Sync'线程,那么类型系统应该禁止跨线程共享,对吗?而且libzmq C API根本不使用回调函数AFAIK。 – rotty

相关问题