Я использую Rocket с State
, который он передает HTTP-запросам.Эта структура содержит Mutex<DatastoreInstance>
, который предоставляет доступ к базе данных SQLite и заблокирован мьютексом, чтобы сделать чтение и запись безопасными.
pub struct DatastoreInstance {
conn: Connection,
}
Когда структура DatastoreInstance
выглядела так, только с SQLiteВ связи с этим все работало нормально, но я также хотел добавить объект транзакции в эту структуру:
pub struct DatastoreInstance {
conn: Connection,
events_transaction: Transaction,
}
Это не скомпилировалось, поскольку объект Transaction
должен ссылаться на объект Connection
, который должен иметьвремя жизни, о котором оно знает.Используемые мной объекты Connection
и Transaction
в rusqlite определены следующим образом:
pub struct Connection {
db: RefCell<InnerConnection>,
cache: StatementCache,
path: Option<PathBuf>,
}
pub struct Transaction<'conn> {
conn: &'conn Connection,
drop_behavior: DropBehavior,
}
Чтобы решить проблемы времени жизни, мне пришлось добавить эти параметры времени жизни, чтобы он работал:
pub struct DatastoreInstance<'a> {
conn: Connection,
events_transaction: Transaction<'a>,
}
Это был результат, который должен был работать в соответствии с моим пониманием времени жизни и мьютексов, но теперь я получаю ошибку компилятора, говорящую мне:
`std::cell::RefCell<lru_cache::LruCache<std::string::String, rusqlite::raw_statement::RawStatement>>` cannot be shared between threads safely
|
= help: within `rusqlite::Connection`, the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<lru_cache::LruCache<std::string::String, rusqlite::raw_statement::RawStatement>>`
= note: required because it appears within the type `rusqlite::cache::StatementCache`
= note: required because it appears within the type `rusqlite::Connection`
= note: required because of the requirements on the impl of `std::marker::Send` for `&rusqlite::Connection`
= note: required because it appears within the type `datastore::DatastoreInstance<'_>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<datastore::DatastoreInstance<'_>>`
= note: required because it appears within the type `endpoints::ServerState<'_>`
= note: required by `rocket::State`
Согласно моему пониманию мьютексов,этот код должен быть действительным, потому что вся структура DatastoreInstance
обернута в Mutex
, что должно гарантировать, что только один поток ссылается на этот объект одновременно.
Чего мне не хватает?
Почему компилятор не находит RefCell
безопасным после того, как находится в пределах Connection
, на который ссылается Transaction
, а не только в Connection
?
Должен ли яплохо понимаешь, как работают мьютексы?Мои жизни недействительны и как-то нарушают безопасность чтения / записи?Является ли дизайн с наличием Connection
и Transaction
в одной структуре плохим дизайном, который нарушает безопасность чтения / записи?Нужно ли каким-то образом перепроектировать мои структуры данных, чтобы сделать это безопасным?Или я просто упускаю что-то очень очевидное?