Send this stuff over threads

I have been lost for song long...

I want to send this struct over the threads but the classic "some member that is under this struct doesnot implement the SEND trait" comes up.

i did avoid this earlier by creating the struct inside the new thread but now i need to use this struct more than once.(creating every time is very expensive).

the struct i want to send between threads:

pub struct ThreadVideoStream {
    input_ctx: InputContext, // ffmpeg input ctx is type aliased
    decoder: VideoDecoder,   // ffmpeg video decoder is type aliased
    scalar: Scaler,          // ffmpeg scaler is type aliased
    stream_index: usize,
    eof_sent: bool,
    fps: f64,
    time_base: Rational,
}

I can't come up any solutions like how would i avoid creating this struct more than once.
I did smth like this before:

  let video_path = ...;
   thread::spawn(move || {
           let mut video_stream = ThreadVideoStream::new(video_path);

          App::send_framemeta(&mut video_stream, tx);
        });

now i want to do this but its not possible:

    let video_stream = ThreadVideoStream::new(video_path);
        self.tvideo_stream = Some(Arc::new(video_stream));
        let first_stream = self.tvideo_stream.unwrap().clone(); // NOTE: unwrap
        thread::spawn(move || {
            App::send_framemeta(&mut first_stream, tx);
        });

please excuse my english

Some context would be useful. E.g. are you defining this struct yourself? How about the types of the fields it contains. If there are any open-source libraries involves, particularly in the field types that actually cause the missing Send implementation, that would be a useful thing to reference. That would help regardless of solution because the non-Send-able part of your struct is presumably also the most interesting part / the part that's expensive to re-create.

Possible solutions do (obviously) include either the quest to make the struct Send able between threads somehow, after all; or to work around the problem somehow. It's hard to give concrete tips though without a bit more context (e.g. of the kind I suggested above).

If you aren't sure which part of your struct cause the non-Send-ness, the compilation error should actually be telling you that information, if I remember correctly. Feel free to share the full actual error message as well, that's generally useful contex to give when asking for help (and mentioning an error message).

Sorry for vague info,Here's full context(hopefully):

-> Yes,I am defining the struct Myself.
-> The types are defined like this by me:

type InputContext = ffmpeg_next::format::context::Input;
type VideoDecoder = ffmpeg_next::decoder::Video;
type Scaler = ffmpeg_next::software::scaling::Context;
type VideoFrame = ffmpeg_next::frame::Video;

-> Yup,I am using ffmpeg-next
-> i am pretty sure the InputContext,VideoScaler has types that does not implement the SEND trait.
-> ERRROS are below but too long i am pasting short version and full version of error below:

SHORT VERSION

1. `*mut AVFormatContext` cannot be shared between threads safely
   within `ThreadVideoStream`, the trait `Sync` is not implemented for `*mut AVFormatContext`
   required for `Arc<ThreadVideoStream>` to implement `Send` [E0277]
   lib.rs:809:9: required by a bound introduced by this call
   input.rs:13:12: required because it appears within the type `ffmpeg_next::format::context::Input`
   lib.rs:93:12: required because it appears within the type `ThreadVideoStream`
   lib.rs:809:23: required because it's used within this closure
   functions.rs:128:8: required by a bound in `spawn`
2. required by a bound introduced by this call [E0277]
   lib.rs:809:23: original diagnostic
3. required because it's used within this closure [E0277]
   lib.rs:809:23: original diagnostic
4. `*mut SwsContext` cannot be shared between threads safely
   within `ThreadVideoStream`, the trait `Sync` is not implemented for `*mut SwsContext`
   required for `Arc<ThreadVideoStream>` to implement `Send` [E0277]
   lib.rs:809:9: required by a bound introduced by this call
   context.rs:16:12: required because it appears within the type `ffmpeg_next::software::scaling::Context`
   lib.rs:93:12: required because it appears within the type `ThreadVideoStream`
   lib.rs:809:23: required because it's used within this closure
   functions.rs:128:8: required by a bound in `spawn`
5. `*mut SwsContext` cannot be sent between threads safely
   within `ThreadVideoStream`, the trait `Send` is not implemented for `*mut SwsContext`
   required for `Arc<ThreadVideoStream>` to implement `Send` [E0277]
   lib.rs:809:9: required by a bound introduced by this call
   context.rs:16:12: required because it appears within the type `ffmpeg_next::software::scaling::Context`
   lib.rs:93:12: required because it appears within the type `ThreadVideoStream`
   lib.rs:809:23: required because it's used within this closure
   functions.rs:128:8: required by a bound in `spawn`
6. `Rc<Destructor>` cannot be shared between threads safely
   within `ThreadVideoStream`, the trait `Sync` is not implemented for `Rc<Destructor>`
   required for `Arc<ThreadVideoStream>` to implement `Send` [E0277]
   lib.rs:809:9: required by a bound introduced by this call
   common.rs:11:12: required because it appears within the type `ffmpeg_next::format::context::common::Context`
   input.rs:13:12: required because it appears within the type `ffmpeg_next::format::context::Input`
   lib.rs:93:12: required because it appears within the type `ThreadVideoStream`
   lib.rs:809:23: required because it's used within this closure
   functions.rs:128:8: required by a bound in `spawn`
7. `*mut AVCodecContext` cannot be shared between threads safely
   within `ThreadVideoStream`, the trait `Sync` is not implemented for `*mut AVCodecContext`
   required for `Arc<ThreadVideoStream>` to implement `Send` [E0277]
   lib.rs:809:9: required by a bound introduced by this call
   context.rs:13:12: required because it appears within the type `ffmpeg_next::codec::Context`
   decoder.rs:9:12: required because it appears within the type `ffmpeg_next::decoder::Decoder`
   opened.rs:9:12: required because it appears within the type `Opened`
   video.rs:18:12: required because it appears within the type `ffmpeg_next::decoder::Video`
   lib.rs:93:12: required because it appears within the type `ThreadVideoStream`
   lib.rs:809:23: required because it's used within this closure
   functions.rs:128:8: required by a bound in `spawn`
8. `Rc<(dyn std::any::Any + 'static)>` cannot be shared between threads safely
   within `ThreadVideoStream`, the trait `Sync` is not implemented for `Rc<(dyn std::any::Any + 'static)>`
   required for `Arc<ThreadVideoStream>` to implement `Send` [E0277]
   lib.rs:809:9: required by a bound introduced by this call
   option.rs:600:10: required because it appears within the type `Option<Rc<(dyn std::any::Any + 'static)>>`
   context.rs:13:12: required because it appears within the type `ffmpeg_next::codec::Context`
   decoder.rs:9:12: required because it appears within the type `ffmpeg_next::decoder::Decoder`
   opened.rs:9:12: required because it appears within the type `Opened`
   video.rs:18:12: required because it appears within the type `ffmpeg_next::decoder::Video`
   lib.rs:93:12: required because it appears within the type `ThreadVideoStream`
   lib.rs:809:23: required because it's used within this closure
   functions.rs:128:8: required by a bound in `spawn`

Full error

error[E0277]: `*mut AVFormatContext` cannot be shared between threads safely
   --> src/lib.rs:809:23
    |
809 |           thread::spawn(move || {
    |  _________-------------_^
    | |         |
    | |         required by a bound introduced by this call
810 | |             App::send_framemeta(&mut first_stream, tx);
811 | |         });
    | |_________^ `*mut AVFormatContext` cannot be shared between threads safely
    |
    = help: within `ThreadVideoStream`, the trait `Sync` is not implemented for `*mut AVFormatContext`
note: required because it appears within the type `ffmpeg_next::format::context::Input`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/format/context/input.rs:13:12
    |
 13 | pub struct Input {
    |            ^^^^^
note: required because it appears within the type `ThreadVideoStream`
   --> src/lib.rs:93:12
    |
 93 | pub struct ThreadVideoStream {
    |            ^^^^^^^^^^^^^^^^^
    = note: required for `Arc<ThreadVideoStream>` to implement `Send`
note: required because it's used within this closure
   --> src/lib.rs:809:23
    |
809 |         thread::spawn(move || {
    |                       ^^^^^^^
note: required by a bound in `spawn`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/functions.rs:128:8
    |
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    |        ----- required by a bound in this function
...
128 |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`

error[E0277]: `*mut SwsContext` cannot be shared between threads safely
   --> src/lib.rs:809:23
    |
809 |           thread::spawn(move || {
    |  _________-------------_^
    | |         |
    | |         required by a bound introduced by this call
810 | |             App::send_framemeta(&mut first_stream, tx);
811 | |         });
    | |_________^ `*mut SwsContext` cannot be shared between threads safely
    |
    = help: within `ThreadVideoStream`, the trait `Sync` is not implemented for `*mut SwsContext`
note: required because it appears within the type `ffmpeg_next::software::scaling::Context`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/software/scaling/context.rs:16:12
    |
 16 | pub struct Context {
    |            ^^^^^^^
note: required because it appears within the type `ThreadVideoStream`
   --> src/lib.rs:93:12
    |
 93 | pub struct ThreadVideoStream {
    |            ^^^^^^^^^^^^^^^^^
    = note: required for `Arc<ThreadVideoStream>` to implement `Send`
note: required because it's used within this closure
   --> src/lib.rs:809:23
    |
809 |         thread::spawn(move || {
    |                       ^^^^^^^
note: required by a bound in `spawn`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/functions.rs:128:8
    |
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    |        ----- required by a bound in this function
...
128 |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`

error[E0277]: `*mut SwsContext` cannot be sent between threads safely
   --> src/lib.rs:809:23
    |
809 |           thread::spawn(move || {
    |  _________-------------_^
    | |         |
    | |         required by a bound introduced by this call
810 | |             App::send_framemeta(&mut first_stream, tx);
811 | |         });
    | |_________^ `*mut SwsContext` cannot be sent between threads safely
    |
    = help: within `ThreadVideoStream`, the trait `Send` is not implemented for `*mut SwsContext`
note: required because it appears within the type `ffmpeg_next::software::scaling::Context`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/software/scaling/context.rs:16:12
    |
 16 | pub struct Context {
    |            ^^^^^^^
note: required because it appears within the type `ThreadVideoStream`
   --> src/lib.rs:93:12
    |
 93 | pub struct ThreadVideoStream {
    |            ^^^^^^^^^^^^^^^^^
    = note: required for `Arc<ThreadVideoStream>` to implement `Send`
note: required because it's used within this closure
   --> src/lib.rs:809:23
    |
809 |         thread::spawn(move || {
    |                       ^^^^^^^
note: required by a bound in `spawn`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/functions.rs:128:8
    |
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    |        ----- required by a bound in this function
...
128 |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`

error[E0277]: `Rc<Destructor>` cannot be shared between threads safely
   --> src/lib.rs:809:23
    |
809 |           thread::spawn(move || {
    |  _________-------------_^
    | |         |
    | |         required by a bound introduced by this call
810 | |             App::send_framemeta(&mut first_stream, tx);
811 | |         });
    | |_________^ `Rc<Destructor>` cannot be shared between threads safely
    |
    = help: within `ThreadVideoStream`, the trait `Sync` is not implemented for `Rc<Destructor>`
note: required because it appears within the type `ffmpeg_next::format::context::common::Context`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/format/context/common.rs:11:12
    |
 11 | pub struct Context {
    |            ^^^^^^^
note: required because it appears within the type `ffmpeg_next::format::context::Input`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/format/context/input.rs:13:12
    |
 13 | pub struct Input {
    |            ^^^^^
note: required because it appears within the type `ThreadVideoStream`
   --> src/lib.rs:93:12
    |
 93 | pub struct ThreadVideoStream {
    |            ^^^^^^^^^^^^^^^^^
    = note: required for `Arc<ThreadVideoStream>` to implement `Send`
note: required because it's used within this closure
   --> src/lib.rs:809:23
    |
809 |         thread::spawn(move || {
    |                       ^^^^^^^
note: required by a bound in `spawn`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/functions.rs:128:8
    |
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    |        ----- required by a bound in this function
...
128 |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`

error[E0277]: `*mut AVCodecContext` cannot be shared between threads safely
   --> src/lib.rs:809:23
    |
809 |           thread::spawn(move || {
    |  _________-------------_^
    | |         |
    | |         required by a bound introduced by this call
810 | |             App::send_framemeta(&mut first_stream, tx);
811 | |         });
    | |_________^ `*mut AVCodecContext` cannot be shared between threads safely
    |
    = help: within `ThreadVideoStream`, the trait `Sync` is not implemented for `*mut AVCodecContext`
note: required because it appears within the type `ffmpeg_next::codec::Context`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/context.rs:13:12
    |
 13 | pub struct Context {
    |            ^^^^^^^
note: required because it appears within the type `ffmpeg_next::decoder::Decoder`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/decoder/decoder.rs:9:12
    |
  9 | pub struct Decoder(pub Context);
    |            ^^^^^^^
note: required because it appears within the type `Opened`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/decoder/opened.rs:9:12
    |
  9 | pub struct Opened(pub Decoder);
    |            ^^^^^^
note: required because it appears within the type `ffmpeg_next::decoder::Video`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/decoder/video.rs:18:12
    |
 18 | pub struct Video(pub Opened);
    |            ^^^^^
note: required because it appears within the type `ThreadVideoStream`
   --> src/lib.rs:93:12
    |
 93 | pub struct ThreadVideoStream {
    |            ^^^^^^^^^^^^^^^^^
    = note: required for `Arc<ThreadVideoStream>` to implement `Send`
note: required because it's used within this closure
   --> src/lib.rs:809:23
    |
809 |         thread::spawn(move || {
    |                       ^^^^^^^
note: required by a bound in `spawn`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/functions.rs:128:8
    |
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    |        ----- required by a bound in this function
...
128 |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`

error[E0277]: `Rc<(dyn std::any::Any + 'static)>` cannot be shared between threads safely
   --> src/lib.rs:809:23
    |
809 |           thread::spawn(move || {
    |  _________-------------_^
    | |         |
    | |         required by a bound introduced by this call
810 | |             App::send_framemeta(&mut first_stream, tx);
811 | |         });
    | |_________^ `Rc<(dyn std::any::Any + 'static)>` cannot be shared between threads safely
    |
    = help: within `ThreadVideoStream`, the trait `Sync` is not implemented for `Rc<(dyn std::any::Any + 'static)>`
note: required because it appears within the type `Option<Rc<(dyn std::any::Any + 'static)>>`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:600:10
    |
600 | pub enum Option<T> {
    |          ^^^^^^
note: required because it appears within the type `ffmpeg_next::codec::Context`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/context.rs:13:12
    |
 13 | pub struct Context {
    |            ^^^^^^^
note: required because it appears within the type `ffmpeg_next::decoder::Decoder`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/decoder/decoder.rs:9:12
    |
  9 | pub struct Decoder(pub Context);
    |            ^^^^^^^
note: required because it appears within the type `Opened`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/decoder/opened.rs:9:12
    |
  9 | pub struct Opened(pub Decoder);
    |            ^^^^^^
note: required because it appears within the type `ffmpeg_next::decoder::Video`
   --> /home/sudip/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ffmpeg-next-8.1.0/src/codec/decoder/video.rs:18:12
    |
 18 | pub struct Video(pub Opened);
    |            ^^^^^
note: required because it appears within the type `ThreadVideoStream`
   --> src/lib.rs:93:12
    |
 93 | pub struct ThreadVideoStream {
    |            ^^^^^^^^^^^^^^^^^
    = note: required for `Arc<ThreadVideoStream>` to implement `Send`
note: required because it's used within this closure
   --> src/lib.rs:809:23
    |
809 |         thread::spawn(move || {
    |                       ^^^^^^^
note: required by a bound in `spawn`
   --> /home/sudip/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/functions.rs:128:8
    |
125 | pub fn spawn<F, T>(f: F) -> JoinHandle<T>
    |        ----- required by a bound in this function
...
128 |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `neo-kut` (lib) due to 6 previous errors

ffmpeg APIs are not thread safe. You just cannot do that.

yup i expected that but what do i do now..

You cannot send an exclusive borrow (&mut T) across threads. The best thing you could do is to read about the Send trait here: Send and Sync - The Rustonomicon.

The most basic workaround is to use synchronization objects from the sync module such as Arc and Mutex. Like this:

let wrapped_video_stream = Arc::new(ThreadVideoStream::new(Mutex::new(video_path)));

// Make sure send_framemeta now expects an Arc<Mutex<ThreadVideoStream>>
App::send_framemeta(wrapped_video_stream, tx);

This is just for the outer layer. The error message you posted also indicates several other compilation errors downstream, always make sure to read errros carefully.

yup i tried doing the Arc one,but that's not the problem.We can't send The struct between threads because some types inside this struct doesnot implement the Send trait.

You have to look into whether ffmpeg pointers can be sent to other threads. If InputContext is a pointer which "owns" the context, then you could use unsafe impl Send for ThreadVideoStream {}. But you have to be extremely careful here, since for example ffmpeg contexts may deal with thread local data, in that case you simply can not send the pointers between threads. Period.

If you use an existing wrapper instead of raw pointers, then it should already implement Send/Sync where it's appropriate.

Looking at the types involved, it looks like InputContext and VideoDecoder do implement Send but not Sync, whereas Scaler (= …::scaling::Context) implements neither.

The code you're actually testing does however apparently try to share these values between threads, not just send them. This is something that use of Mutex could e.g. avoid, however the Send requirement will always remain even with Mutex.

In this type of situation, what you should probably do is arrange to reuse the thread.

Create a thread dedicated to this purpose, and use a channel (std::sync::mpsc, for example) to send it new work to do.

Thank you,Now i am using dedicated channel to send commands,entirely removing the need to make a new struct