I have a TcpStream, and i'm trying to create a dedicated thread to read from TcpStream and the main thread should do the write only, so i wrapped the TcpStream inside an Arc to share ownership.
Here is my code
fn main() {
let mut tcp_stream = TcpStream::connect("127.0.0.1:8080").unwrap();
let tcp_stream = Arc::new(&mut tcp_stream);
}
fn read_from_stream(tcp_stream: Arc<&mut TcpStream>) {
let mut buffer = String::new();
tcp_stream.read_to_string(&mut buffer);
}
I got the error Cannot borrow data in Arc as mutable. But the tcp_stream needs to be mutable in order to call read_to_string method.
What should i do to make this work?
While Arc does inhibit mutability, in this case that's not an issue because &TcpStream implements Read.
Therefore you can wrap TcpStream (not &mut TcpStream) in Arc and call read_to_string() on the shared &TcpStream reference obtained with Arc::as_ref():
fn main() {
let tcp_stream = TcpStream::connect("127.0.0.1:8080").unwrap();
let tcp_stream = Arc::new(tcp_stream);
}
fn read_from_stream(tcp_stream: Arc<TcpStream>) {
let mut buffer = String::new();
tcp_stream.as_ref().read_to_string(&mut buffer);
}
Playground
From the docs:
Shared references in Rust disallow mutation by default, and Arc is no
exception: you cannot generally obtain a mutable reference to
something inside an Arc. If you need to mutate through an Arc, use
Mutex, RwLock, or one of the Atomic types.
In your case, I would go either with Mutex or RwLock.
Example using Mutex:
fn main()
{
let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap();
let stream = Arc::new(Mutex::new(stream));
read_from_stream(stream);
}
fn read_from_stream(tcp_stream: Arc<Mutex<TcpStream>>)
{
let mut buffer = String::new();
let mut tcp_stream = tcp_stream.lock().unwrap();
tcp_stream.read_to_string(&mut buffer).unwrap();
}
Related
I need to allocate structs with a drop trait inside a for loop and have a mutable reference for downstream processing. I have created this minimal example code that I can't compile with rust version 1.59. I have tried using the internal mutability with Rc and RefCell as well.
use std::cell::RefCell;
use std::rc::Rc;
// MyVec with Drop Trait
struct MyVec {
vec: Vec<i32>,
}
impl Drop for MyVec {
fn drop(&mut self) {
println!("Dropping MyVec with data `{:?}`!", self.vec);
}
}
impl MyVec {
// Get a mutable slice
fn mut_slice(&mut self) -> &mut [i32]{
return &mut self.vec[..]
}
}
pub fn test() {
// Needed for downstream purposes
let mut all_slices = Vec::new();
// Storing reference counter Rc and RefCell combo
// Hoping to prevent allocated MyVec objects from dropping and have one mutable reference
let mut all_refs = Vec::new();
for _i in 0..1 {
let my_vec = Rc::new(RefCell::new(MyVec {
vec: vec![1, 2, 3]
}));
// Make a clone of my_vec to prevent it from dropping
all_refs.push(Rc::clone(&my_vec));
let mut my_vec_mut = my_vec.borrow_mut();
let x = my_vec_mut.mut_slice();
all_slices.push(x);
}
println!("{:?}", all_slices);
}
The same code works when I unroll the loop and write the following code:
pub fn test() {
// Needed for downstream purposes
let mut all_slices = Vec::new();
// Storing reference counter Rc and RefCell combo
// Hoping to prevent allocated MyVec objects from dropping and have one mutable reference
let mut all_refs = Vec::new();
let my_vec = Rc::new(RefCell::new(MyVec {
vec: vec![1, 2, 3]
}));
// Make a clone of my_vec to prevent it from dropping
all_refs.push(Rc::clone(&my_vec));
let mut my_vec_mut = my_vec.borrow_mut();
let x = my_vec_mut.mut_slice();
all_slices.push(x);
println!("{:?}", all_slices);
}
Update: Thanks to Masklinn's comments, I fixed the code. I needed to create objects in the loop and required a mutable reference to its internal data field outside the scope of the loop. The rust compiler showed an error that the references outlive the object itself. Finally, I used a separate loop to allocate the objects and a second loop with iter_mut to create mutable references. Here is the final code:
pub fn test() {
// Needed for downstream purposes
let mut all_slices = Vec::new();
// Hoping to prevent allocated MyVec objects from dropping and have one mutable reference
let mut all_vecs = Vec::new();
for _i in 0..1 {
all_vecs.push(MyVec {
vec: vec![1, 2, 3]
});
}
for my_vec in all_vecs.iter_mut() {
all_slices.push(my_vec.mut_slice());
}
println!("{:?}", all_slices);
}
I'm writing a program that will concurrently call an API and fill a VecDeque with integers from the response JSON. Since these will be running concurrently, I wrapped the VecDeque in a Mutex. When I test the code and try to push an integer into the VecDeque, I get an error.
#[tokio::main]
async fn main() -> Result<(), ()> {
let client = Client::new();
let mut tank = Mutex::new(VecDeque::new());
// let mut tank = VecDeque::with_capacity(10);
tank.push_back(2);
tank.push_back(3);
println!("{:?}", tank);
Ok(())
}
tank.push_back(2);
^^^^^^^^^ method not found in `std::sync::Mutex<VecDeque<_>>
Do I need to create the VecDeque inside a struct instead?
As per the suggestion, I needed to lock before changing the VecDeque. It works now:
#[tokio::main]
async fn main() -> Result<(), ()> {
let client = Client::new();
let mut tank = Mutex::new(VecDeque::new());
let mut tank = tank.lock().unwrap().push_back(2);
let mut tank = tank.lock().unwrap().push_back(3);
println!("{:?}", tank);
Ok(())
}
I am trying to write a tcp server with async-std, in order to resolve the confilice of read-write borrow check, I found a strange way:
use async_std::prelude::*;
use async_std::task;
use async_std::net::TcpListener;
use async_std::io::BufReader;
fn main() {
task::block_on(async {
let listener = TcpListener::bind("0.0.0.0:9000").await.unwrap();
let mut incoming = listener.incoming();
while let Some(stream) = incoming.next().await {
let stream = stream.unwrap();
println!("Client Addr: {:?}", stream.peer_addr().unwrap());
task::spawn( async move {
let (reader, mut writer) = (&stream, &stream); // Stange here <-----
let reader = BufReader::new(reader);
let mut lines = reader.lines();
while let Some(line) = lines.next().await {
let mut line = line.unwrap();
line.push('x');
line.push('\n');
writer.write_all(line.as_bytes()).await.unwrap();
}
});
}
});
}
Strange:
let (reader, mut writer) = (&stream, &stream); // Stange here <-----
I wrote a verification program following this method:
fn main() {
let mut arr = vec![1, 2, 3, 4];
let (r, mut w) = (&arr, &arr);
for v in r.iter() {
if v == &2 {
w.push(5);
}
}
dbg!(arr);
}
got error:
error[E0596]: cannot borrow `*w` as mutable, as it is behind a `&` reference
can anyone explain it ?
This works because TcpStream has the following impls:
impl Read for TcpStream
impl Write for TcpStream
impl<'_> Read for &'_ TcpStream
impl<'_> Write for &'_ TcpStream
The first two are the "normal" ones, the last two are the "special" ones that allow you to do this reader/writer trick.
For example: The read() trait method is defined like this:
pub fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> ImplFuture<Result<usize>>
When you do stream.read(buf), you're using the impl Read for TcpStream impl. Therefore, you're calling the method with self being of type &mut TcpStream.
When you do let reader = &stream; reader.read(buf), you're using the impl<'_> Read for &'_ TcpStream. Therefore, you're calling the method with self being of type &mut &TcpStream.
I am trying to use the read and write of a tcp stream in different threads. This is what I currently have:
use tokio::prelude::*;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut stream = TcpStream::connect("localhost:8080").await?;
let (mut read, mut write) = stream.split();
tokio::spawn(async move {
loop {
let mut buf = [0u8; 32];
read.read(&mut buf).await.unwrap();
println!("{}", std::str::from_utf8(&buf));
}
});
Ok(())
}
Im going to use another thread for the write. My problem is that I get the error that 'stream' is dropped while still borrowed.
That happens due to the method signature of Tokio::split, as you can see it takes &mut self, so its part cannot be used in a tokio::spawn future argument due to the 'static bound. So, this is exactly what the error says.
What you are searching is tokio::io::split. Playground
use tokio::prelude::*;
use tokio::net::TcpStream;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut stream = TcpStream::connect("localhost:8080").await?;
let (mut read, mut write) = tokio::io::split(stream);
tokio::spawn(async move {
loop {
let mut buf = [0u8; 32];
read.read(&mut buf).await.unwrap();
println!("{:?}", std::str::from_utf8(&buf));
}
});
Ok(())
}
Reading https://users.rust-lang.org/t/why-i-have-to-use-tokio-tcpstream-split-for-concurrent-read-writes/47755/3
And it suggests to use into_split it is more efficient.
tokio::io::split uses a Mutex which into_split apparently does not have (specific to TcpStream)
I have a struct which contains both data and a writer which will eventually be used to write the data. The struct is wrapped in a RefCell. Here's a small reproduction:
use std::cell::RefCell;
use std::io::Write;
struct Data {
string: String,
}
struct S {
data: Data,
writer: Vec<u8>,
}
fn write(s: RefCell<S>) {
let mut mut_s = s.borrow_mut();
let str = &mut_s.data.string;
mut_s.writer.write(str.as_bytes());
}
The compiler is angry:
error[E0502]: cannot borrow `mut_s` as mutable because it is also borrowed as immutable
--> src\main.rs:16:5
|
15 | let str = &mut_s.data.string;
| ----- immutable borrow occurs here
16 | mut_s.writer.write(str.as_bytes());
| ^^^^^ mutable borrow occurs here
17 | }
| - immutable borrow ends here
Is there a different API I should use?
You can manually invoke DerefMut and then save the resulting reference:
fn write(s: RefCell<S>) {
let mut mut_s = s.borrow_mut();
let mut tmp = &mut *mut_s; // Here
let str = &tmp.data.string;
tmp.writer.write(str.as_bytes());
}
Or in one line:
fn write(s: RefCell<S>) {
let mut_s = &mut *s.borrow_mut(); // Here
let str = &mut_s.data.string;
mut_s.writer.write(str.as_bytes());
}
The problem is that borrow_mut doesn't return your struct directly — it returns a RefMut. Normally, this is transparent as this struct implements Deref and DerefMut, so any methods called on it are passed to the underlying type. The pseudo-expanded code looks something like this:
use std::cell::RefMut;
use std::ops::{Deref, DerefMut};
fn write(s: RefCell<S>) {
let mut mut_s: RefMut<S> = s.borrow_mut();
let str = &Deref::deref(&mut_s).data.string;
DerefMut::deref_mut(&mut mut_s).writer.write(str.as_bytes());
}
Rust doesn't track field-level borrows across function calls (even for Deref::deref or DerefMut::deref_mut). This causes your error, as the deref_mut method would need to be called during the outstanding borrow from the previous Deref::deref.
The expanded version with the explicit borrow looks like this, with a single call to Deref::deref_mut:
use std::cell::RefMut;
use std::ops::DerefMut;
fn write(s: RefCell<S>) {
let mut mut_s: RefMut<S> = s.borrow_mut();
let tmp: &mut S = DerefMut::deref_mut(&mut mut_s);
let str = &tmp.data.string;
tmp.writer.write(str.as_bytes());
}
The compiler can then track that the two borrows from that temporary value are disjoint.
Note that this problem isn't unique to RefCell! Any type that implements DerefMut can experience the same problem. Here's some from the standard library:
Box
MutexGuard (from Mutex)
PeekMut (from BinaryHeap)
RwLockWriteGuard (from RwLock)
String
Vec
Pin