2016-11-18 141 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

相關問題