<div dir="ltr">Hi Sebastian,<div><br></div><div>> It's a bit unfortunate that the `std::sync::mpsc::Sender` is not `Sync`<br>> but you don't need the full `Arc<Mutex<_>>` machinery for making this<br>> work.<br>> <br>> You can move the sender into your callback, `clone()` it every time you<br>> need to send something through it and use the clone for sending.<br>> <br>> Internally the sender uses an `Arc` etc. so this is cheap, and cheaper<br>> than putting another `Mutex` around everything.<br></div><div><br></div><div>To provide a brief snippet of code, here's roughly what I'm doing:</div><div><br></div><div>// SNIPPET</div><div><br></div><div>// gst/glutin boilerplate</div><div>let event_loop = glutin::event_loop::EventLoop::new();<br></div><div>// more gst/glutin boilerplate</div><div>let decodebin = gst::ElementFactory::make("decodebin", None).unwrap();<br></div><div>// etc...</div><div>let event_loop_proxy = Arc::new(Mutex::new(event_loop.create_proxy()));</div><div>decodebin.connect_pad_added(move |dbin, src_pad| {<br></div><div> // ...</div><div> let appsink = gst::ElementFactory::make("appsink", None)</div> .unwrap()<br> .dynamic_cast::<gst_app::AppSink>()<br> .unwrap();<div> let event_loop_proxy = event_loop_proxy.clone();<br><div> appsink.set_callbacks(gst_app::AppSinkCallbacks::builder()</div><div> .new_sample(move |appsink| {</div><div> let el = event_loop_proxy.lock().unwrap();</div><div> el.send_event(/* event */);</div><div> // etc</div><div> }).build(),</div><div> );</div><div> // ...</div><div>});</div><div><br></div><div>// END SNIPPET</div><div><br></div><div>If I understand your suggestion correctly, you're saying that the Arc+Mutex shouldn't be required, and I can simply clone the event loop proxy (which is replaceable with an mpsc channel for this example) and send that into the first closure, then inside that closure, clone it again and send it into the appsink closure. However, this is exactly what I was trying before moving to the Arc+Mutex approach, as attempting to move the cloned event loop (or mpsc sender) into only the decodebin closure causes rust to complain about the event loop not being Sync. For instance, attempting the following:</div><div><br></div><div><div>// SNIPPET</div><div><br></div><div>// gst/glutin boilerplate</div><div>let event_loop = glutin::event_loop::EventLoop::new();<br></div><div>// more gst/glutin boilerplate</div><div>let decodebin = gst::ElementFactory::make("decodebin", None).unwrap();<br></div><div>// etc...</div><div>// (This will also fail if I clone the proxy prior to attempting to move it. However,</div><div>// cloning it shouldn't be required in the first place since I'm not using the</div><div>// proxy outside of the closure.)</div><div>let event_loop_proxy = event_loop.create_proxy();</div><div>decodebin.connect_pad_added(move |dbin, src_pad| {<br></div><div> // ...</div><div> let appsink = gst::ElementFactory::make("appsink", None)</div> .unwrap()<br> .dynamic_cast::<gst_app::AppSink>()<br> .unwrap();<div> let event_loop_proxy_clone = event_loop_proxy.clone();<br><div> appsink.set_callbacks(gst_app::AppSinkCallbacks::builder()</div><div> .new_sample(move |appsink| {</div><div>
event_loop_proxy_clone.send_event(/* event */);</div><div> // etc</div><div> }).build(),</div><div> );</div><div> // ...</div><div>});</div><div><br></div><div>// END SNIPPET</div></div></div><div><br></div><div>fails at line "decodebin.connect_pad_added ..." with the following:</div><div>> `std::sync::mpsc::Sender<Message>` cannot be shared between threads safely<br>> help: within `[closure@src\main.rs:_:_: _:_]`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<Message>`<br>> note: required because it appears within the type `[closure@src\main.rs:_:_: _:_]`<br></div><div><br></div><div>Am I misunderstanding your suggestion?</div></div><div><br></div><div>Regarding crossbeam, the Sender which rustc is referring to here lives within a glutin::event_loop::EventLoop, so a crossbeam channel wouldn't be a drop-in replacement. It would be fairly trivial to make it work, but I'd like to avoid additional dependencies if I can. That said, if a crossbeam channel ends up being the most efficient option, that's certainly what I'll go with.</div><div><br></div><div>Thanks,</div><div>Steven</div></div>