【发布时间】:2020-07-28 23:41:17
【问题描述】:
我正在使用a crate 与 Postgres 交互,只需手动编写 sql 查询(Diesel 似乎是我的简单案例),并且在多线程访问数据库客户端时遇到了困难。代码如下:
use postgres::Client;
pub struct Database{
connection: Arc<Client>
}
impl Database {
pub fn from_config(url: &str) -> Database {
//...
}
}
fn main() {
let url: String = //...
let db = db::Database::from_config(&url);
let db_ref = Arc::new(db);
consume(future(Arc::clone(&db_ref))); // <------------------- compile error
}
async fn future(db_ref: Arc<db::Database>){ }
fn consume<F>(f: F)
where F: Send{ }
postgres::Client 定义为
/// A synchronous PostgreSQL client.
pub struct Client {
connection: Connection,
client: tokio_postgres::Client,
}
编译这段代码时,我得到了一些疯狂的错误信息:
error[E0277]: `(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)` cannot be shared between threads safely
--> src/main.rs:17:5
|
17 | consume(future(Arc::clone(&db_ref)));
| ^^^^^^^ `(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)` cannot be shared between threads safely
...
24 | fn consume<F>(f: F)
| ------- required by a bound in this
25 | where F: Send{ }
| ---- required by this bound in `consume`
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)`
= note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)>`
= note: required because it appears within the type `std::boxed::Box<(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)>`
= note: required because it appears within the type `std::pin::Pin<std::boxed::Box<(dyn futures_core::stream::Stream<Item = std::result::Result<tokio_postgres::AsyncMessage, tokio_postgres::error::Error>> + std::marker::Send + 'static)>>`
= note: required because it appears within the type `postgres::connection::Connection`
= note: required because it appears within the type `postgres::client::Client`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<postgres::client::Client>`
= note: required because it appears within the type `db::Database`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<db::Database>`
= note: required because it appears within the type `[static generator@src/main.rs:22:43: 22:46 db_ref:std::sync::Arc<db::Database> {}]`
= note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@src/main.rs:22:43: 22:46 db_ref:std::sync::Arc<db::Database> {}]>`
= note: required because it appears within the type `impl core::future::future::Future`
= note: required because it appears within the type `impl core::future::future::Future`
这似乎意味着Database 没有实现Send。有没有办法实现Send?也许应该使用Mutex 或其他东西来代替Arc?
UPD:
将结构定义替换为
pub struct Database{
connection: Mutex<Client>
}
使错误消失,但完全不清楚为什么......
【问题讨论】:
标签: multithreading rust traits