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

How to access a future through parking_lot guard #6

Closed
dusty-phillips opened this issue Mar 10, 2020 · 2 comments
Closed

How to access a future through parking_lot guard #6

dusty-phillips opened this issue Mar 10, 2020 · 2 comments

Comments

@dusty-phillips
Copy link
Contributor

I have a repro here:

https://github.com/dusty-phillips/async-graphql/blob/parking_lot_repro/examples/parking_lot.rs

In short, I'm using the parking_lot crate to get an RwLock. I've put the lock inside an Arc, and tried to access it from both a query and a mutation. However, I'm getting the following compile errors:

master* $ cargo run --example parking_lot
   Compiling async-graphql v0.10.8 (/home/dusty/beanstalk/async-graphql)
error: future cannot be sent between threads safely
  --> examples/parking_lot.rs:26:1
   |
26 | #[Object]
   | ^^^^^^^^^ future returned by `__resolve_field` is not `Send`
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*mut ()`
note: future is not `Send` as this value is used across an await
  --> examples/parking_lot.rs:30:9
   |
30 |         self.thing.read().get_the_value().await
   |         -----------------^^^^^^^^^^^^^^^^^^^^^^
   |         |
   |         await occurs here, with `self.thing.read()` maybe used later
   |         has type `lock_api::rwlock::RwLockReadGuard<'_, parking_lot::raw_rwlock::RawRwLock, Thing>`
31 |     }
   |     - `self.thing.read()` is later dropped here
   = note: required for the cast to the object type `dyn std::future::Future<Output = std::result::Result<serde_json::value::Value, anyhow::Error>> + std::marker::Send`

error: future cannot be sent between threads safely
  --> examples/parking_lot.rs:38:1
   |
38 | #[Object]
   | ^^^^^^^^^ future returned by `__resolve_field` is not `Send`
   |
   = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `*mut ()`
note: future is not `Send` as this value is used across an await
  --> examples/parking_lot.rs:42:9
   |
42 |         self.thing.write().set_the_value(thing_value).await;
   |         ------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- `self.thing.write()` is later dropped here
   |         |
   |         await occurs here, with `self.thing.write()` maybe used later
   |         has type `lock_api::rwlock::RwLockWriteGuard<'_, parking_lot::raw_rwlock::RawRwLock, Thing>`
   = note: required for the cast to the object type `dyn std::future::Future<Output = std::result::Result<serde_json::value::Value, anyhow::Error>> + std::marker::Send`

error: aborting due to 2 previous errors

error: could not compile `async-graphql`.

To learn more, run the command again with --verbose.

I've tried moving the guard out, but it doesn't seem to work. Intuitively, I can imagine it might not be possible to hold a lock across an await, but there is no compile error when I try to access it in the main() function (line 72) I don't get a compile error there. So the issue seems to be something in the Object macro, but I don't know how to debug. Any suggestions?

@sunli829
Copy link
Collaborator

This could be the reason:
Async_graphql internally calls MutationRoot::set_value with an indirect boxing Pin<Box<dyn Future<Output = Result<()>> + 'a + Send>>, and RwLockGuard does not implement Send.

Synchronization lock is not recommended, use async_std::sync::RwLock to solve this problem.

use async_std::sync::RwLock;

#[Object]
impl MutationRoot {
    #[field]
    async fn set_value(&self, thing_value: String) -> bool {
        self.thing.write().await.set_the_value(thing_value).await;
        true
    }
}

@dusty-phillips
Copy link
Contributor Author

Ah, thanks. That works for my immediate problem, although it shows that I'm going to have a much worse time working with a deeply nested parking_lot lock in a dependent library later. 🤢

zicklag pushed a commit to zicklag/async-graphql that referenced this issue Mar 2, 2021
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

2 participants