Size: a a a

2020 November 14

MB

Mikhail Bazarov in Rust Async
Есть такой пример кода.
При компиляции получаю ошибку:
error[E0277]: `T` cannot be sent between threads safely
 --> src/main.rs:78:20
  |
78 |         let addr = Actor::start_in_arbiter(&arbiter, |_| self);
  |                    ^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely
  |
  = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<T>`
  = note: required because it appears within the type `Data<T>`
  = note: required because it appears within the type `MyActor<T>`
  = note: required because it appears within the type `[closure@src/main.rs:78:54: 78:62 self:MyActor<T>]`
  = note: required by `actix::Actor::start_in_arbiter`
help: consider further restricting this bound
  |
61 | impl<T: Unpin + 'static + std::marker::Send> MyActor<T> {
источник

MB

Mikhail Bazarov in Rust Async
Добавление маркера Send не помогает(
источник

IB

Ivan Boldyrev in Rust Async
Mikhail Bazarov
Добавление маркера Send не помогает(
Возможно, потому, что начинает требоваться ещё и Sync?
источник

MB

Mikhail Bazarov in Rust Async
error[E0599]: no function or associated item named `tick` found for struct `MyActor<T>` in the current scope
 --> src/main.rs:93:48
  |
55 | struct MyActor<T> {
  | ----------------- function or associated item `tick` not found for this
...
93 |         IntervalFunc::new(self.interval, Self::tick)
  |                                                ^^^^ function or associated item not found in `MyActor<T>`
  |
  = note: the method `tick` exists but the following trait bounds were not satisfied:
          `T: std::marker::Send`
          `T: std::marker::Sync`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
источник

IB

Ivan Boldyrev in Rust Async
У тебя для разных частей программы указаны разные ограничения.  В коде, который зависит от T без ограничений, ты не можешь использовать реализацию T: Bla, Bla, Bla, очевидно.
источник

MB

Mikhail Bazarov in Rust Async
Почему тогда, если убрать MyActorService и метод run_on_new_arbiter().
Все компилируется, когда у Data<T> нет этих ограничений?
источник

MB

Mikhail Bazarov in Rust Async
И MyActor спокойно спаунится на арбитре
источник

MB

Mikhail Bazarov in Rust Async
Добавил...
pub struct Data<T: ?Sized>(Arc<T>);

unsafe impl<T: ?Sized> Send for Data<T> {}

компилируется и работает
источник

MB

Mikhail Bazarov in Rust Async
насколько это корректно?
источник

MB

Mikail Bagishov in Rust Async
Это некорректно
источник

MB

Mikail Bagishov in Rust Async
Точнее так. Посылать Arc-шки в другой поток можно, но очень осторожно
источник

MB

Mikhail Bazarov in Rust Async
у меня Mutex не предполагается
источник

MB

Mikail Bagishov in Rust Async
Очень важно, что деструктор обьекта, а значит деструктор последнено клона Arc, должен быть вызван в том же потоке, в котором создан первый клон
источник

MB

Mikail Bagishov in Rust Async
Иначе при вызове деструктора будет UB
источник

MB

Mikhail Bazarov in Rust Async
Тут актор выполняется на одном потоке, как и функция в которую передается Data
источник

MB

Mikail Bagishov in Rust Async
А тогда зачем Send?
источник

MB

Mikhail Bazarov in Rust Async
без него не компилируется
источник

MB

Mikail Bagishov in Rust Async
Может быть используемая для акторов библиотека все-таки многопоточная? Или ты настраиваешь ее так, чтобы поток был ровно один?
источник

MB

Mikhail Bazarov in Rust Async
Ограничение Send есть в Actor::start_in_arbiter(...)
источник

MB

Mikhail Bazarov in Rust Async
Mikail Bagishov
Может быть используемая для акторов библиотека все-таки многопоточная? Или ты настраиваешь ее так, чтобы поток был ровно один?
я использую голый actix
и пытаюсь запускать один актор на одном потеке
в этом методе:
pub fn run_on_new_arbiter(self) -> MyActorService<T> {
       let arbiter = Arbiter::new();
       let addr = Actor::start_in_arbiter(&arbiter, |_| self);

       MyActorService {
           actor: addr,
           arbiter,
       }
}
источник