Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when use tokio::spawn i meet problem anyone can help #574

Closed
LinYUAN-code opened this issue Nov 22, 2023 · 6 comments
Closed

when use tokio::spawn i meet problem anyone can help #574

LinYUAN-code opened this issue Nov 22, 2023 · 6 comments

Comments

@LinYUAN-code
Copy link

LinYUAN-code commented Nov 22, 2023

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let addr = "127.0.0.1:8080";
    let listener = TcpListener::bind(addr).await?;
    println!("mysql running on {}", addr);

    loop {
        let (mut socket, _) = listener.accept().await?;
        println!("connected {:?}", socket);
        tokio::spawn(async move {
            let mut buf = [0; 1024];
            let mut command_buffer = String::new();

            let parser = Arc::new(Mutex::new(gen_parser()));
            loop {
                let mut buffer = String::new();

                match socket.read(&mut buf).await {
                    // socket closed
                    Ok(0) => return,
                    Ok(n) => command_buffer.push_str(from_utf8(&buf[0..n]).unwrap()),
                    Err(e) => {
                        eprintln!("failed to read from socket; err = {:?}", e);
                        return;
                    }
                };
                while let Some(index) = command_buffer.find(';') {
                    let command = command_buffer.as_str()[0..=index].to_string();
                    command_buffer = command_buffer.as_str()[(index + 1)..].to_string();

                    println!("{:?}", parser.lock().await.parse(command));
                    if let Err(e) = socket.write_all("detect command".as_bytes()).await {
                        eprintln!("failed to write to socket; err = {:?}", e);
                        return;
                    }
                }
            }
        });
    }
}

error:
future cannot be sent between threads safely
within impl chumsky::Parser<char, Statement, Error = Simple<char>>, the trait Send is not implemented for Rc<recursive::OnceCell<Box<(dyn chumsky::Parser<char, Expr, Error = Simple<char>> + 'static)>>>

@wackbyte
Copy link
Contributor

I think this requires you to enable the sync feature flag for chumksy.

@LinYUAN-code
Copy link
Author

I think this requires you to enable the sync feature flag for chumksy.

How could i do this? sor, i am new to rust.

@wackbyte
Copy link
Contributor

wackbyte commented Nov 22, 2023

In your Cargo.toml, you can enable feature flags on a dependency by doing something like:

[dependencies]
chumsky = { version = "0.9", features = ["sync"] } 

@zesterer
Copy link
Owner

Be aware that the sync feature will likely require some kind of revising before 1.0 is stable. See #543 for more information. It's not yet clear whether that revision will be breaking or not.

@nothendev
Copy link

I don't think the parser lock is even needed here, you could just have an Arc of the parser or you could just not store it and execute gen_parser inline, you won't even need the sync feature

@zesterer
Copy link
Owner

zesterer commented Jan 8, 2024

Unfortunately many parsers (like Recursive) are not Send + Sync because they use Rc internally. I do think that this requirement could be strengthened without issue though, since the added cost of an atomic increment would only apply on parser creation. That said, Recursive specifically might require some sort of lock internally due to the behaviour of .define(...), although interestingly #494 might actually provide a solution to this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants