mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-23 12:01:01 +00:00
threadshare: Stop using reactor::Background and implement it ourselves for now
This commit is contained in:
parent
299c69185e
commit
b939607693
3 changed files with 94 additions and 5 deletions
|
@ -10,6 +10,7 @@ gstreamer = { git = "https://github.com/sdroege/gstreamer-rs" }
|
||||||
gst-plugin = { git = "https://github.com/sdroege/gst-plugin-rs" }
|
gst-plugin = { git = "https://github.com/sdroege/gst-plugin-rs" }
|
||||||
tokio = { git = "https://github.com/tokio-rs/tokio" }
|
tokio = { git = "https://github.com/tokio-rs/tokio" }
|
||||||
tokio-reactor = { git = "https://github.com/tokio-rs/tokio" }
|
tokio-reactor = { git = "https://github.com/tokio-rs/tokio" }
|
||||||
|
tokio-executor = { git = "https://github.com/tokio-rs/tokio" }
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern crate gstreamer as gst;
|
||||||
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate tokio;
|
extern crate tokio;
|
||||||
|
extern crate tokio_executor;
|
||||||
extern crate tokio_reactor;
|
extern crate tokio_reactor;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -25,6 +25,8 @@ use gst_plugin::object::*;
|
||||||
use gst_plugin::element::*;
|
use gst_plugin::element::*;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, Weak};
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
use std::sync::atomic;
|
||||||
|
use std::thread;
|
||||||
use std::u16;
|
use std::u16;
|
||||||
|
|
||||||
use futures::{Async, Future, IntoFuture, Poll, Stream};
|
use futures::{Async, Future, IntoFuture, Poll, Stream};
|
||||||
|
@ -50,13 +52,94 @@ lazy_static!{
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Our own simplified implementation of reactor::Background to allow hooking into its internals
|
||||||
|
const RUNNING: usize = 0;
|
||||||
|
const SHUTDOWN_NOW: usize = 1;
|
||||||
|
const SHUTDOWN: usize = 2;
|
||||||
|
|
||||||
|
struct IOContextRunner {
|
||||||
|
name: String,
|
||||||
|
reactor: reactor::Reactor,
|
||||||
|
shutdown: Arc<atomic::AtomicUsize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IOContextRunner {
|
||||||
|
fn start(name: &str, reactor: reactor::Reactor) -> IOContextShutdown {
|
||||||
|
let handle = reactor.handle().clone();
|
||||||
|
let shutdown = Arc::new(atomic::AtomicUsize::new(RUNNING));
|
||||||
|
let shutdown_clone = shutdown.clone();
|
||||||
|
let name_clone = name.into();
|
||||||
|
let join = thread::spawn(move || {
|
||||||
|
let mut runner = IOContextRunner {
|
||||||
|
reactor: reactor,
|
||||||
|
shutdown: shutdown_clone,
|
||||||
|
name: name_clone,
|
||||||
|
};
|
||||||
|
runner.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
IOContextShutdown {
|
||||||
|
name: name.into(),
|
||||||
|
shutdown: shutdown,
|
||||||
|
handle: handle,
|
||||||
|
join: Some(join),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&mut self) {
|
||||||
|
gst_debug!(CONTEXT_CAT, "Started reactor thread '{}'", self.name);
|
||||||
|
loop {
|
||||||
|
if self.shutdown.load(atomic::Ordering::SeqCst) > RUNNING {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_trace!(CONTEXT_CAT, "Turning reactor '{}'", self.name);
|
||||||
|
self.reactor.turn(None).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for IOContextRunner {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.shutdown.store(SHUTDOWN, atomic::Ordering::SeqCst);
|
||||||
|
gst_debug!(CONTEXT_CAT, "Shut down reactor thread '{}'", self.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IOContextShutdown {
|
||||||
|
name: String,
|
||||||
|
shutdown: Arc<atomic::AtomicUsize>,
|
||||||
|
handle: reactor::Handle,
|
||||||
|
join: Option<thread::JoinHandle<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for IOContextShutdown {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
gst_debug!(CONTEXT_CAT, "Shutting down reactor thread '{}'", self.name);
|
||||||
|
self.shutdown.store(SHUTDOWN_NOW, atomic::Ordering::SeqCst);
|
||||||
|
loop {
|
||||||
|
use tokio_executor::park::Unpark;
|
||||||
|
|
||||||
|
// XXX: Not nice but good enough
|
||||||
|
gst_trace!(CONTEXT_CAT, "Waiting for reactor '{}' shutdown", self.name);
|
||||||
|
self.handle.unpark();
|
||||||
|
thread::yield_now();
|
||||||
|
if self.shutdown.load(atomic::Ordering::SeqCst) == SHUTDOWN {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = self.join.take().unwrap().join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct IOContext(Arc<IOContextInner>);
|
struct IOContext(Arc<IOContextInner>);
|
||||||
|
|
||||||
struct IOContextInner {
|
struct IOContextInner {
|
||||||
name: String,
|
name: String,
|
||||||
reactor: reactor::Background,
|
|
||||||
pool: thread_pool::ThreadPool,
|
pool: thread_pool::ThreadPool,
|
||||||
|
// Only used for dropping
|
||||||
|
_shutdown: IOContextShutdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for IOContextInner {
|
impl Drop for IOContextInner {
|
||||||
|
@ -77,7 +160,7 @@ impl IOContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reactor = reactor::Reactor::new().unwrap().background().unwrap();
|
let reactor = reactor::Reactor::new().unwrap();
|
||||||
|
|
||||||
let handle = reactor.handle().clone();
|
let handle = reactor.handle().clone();
|
||||||
|
|
||||||
|
@ -93,10 +176,12 @@ impl IOContext {
|
||||||
}
|
}
|
||||||
let pool = pool_builder.build();
|
let pool = pool_builder.build();
|
||||||
|
|
||||||
|
let shutdown = IOContextRunner::start(name, reactor);
|
||||||
|
|
||||||
let context = Arc::new(IOContextInner {
|
let context = Arc::new(IOContextInner {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
reactor,
|
|
||||||
pool,
|
pool,
|
||||||
|
_shutdown: shutdown,
|
||||||
});
|
});
|
||||||
contexts.insert(name.into(), Arc::downgrade(&context));
|
contexts.insert(name.into(), Arc::downgrade(&context));
|
||||||
|
|
||||||
|
@ -112,7 +197,7 @@ impl IOContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Workaround for https://github.com/tokio-rs/tokio/issues/207 */
|
// FIXME: Workaround for https://github.com/tokio-rs/tokio/issues/207
|
||||||
struct YieldOnce<E>(Option<()>, PhantomData<E>);
|
struct YieldOnce<E>(Option<()>, PhantomData<E>);
|
||||||
|
|
||||||
impl<E> YieldOnce<E> {
|
impl<E> YieldOnce<E> {
|
||||||
|
@ -316,7 +401,7 @@ impl Stream for SocketStream {
|
||||||
return Ok(Async::NotReady);
|
return Ok(Async::NotReady);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_ne!(inner.state, SocketState::Unscheduled);
|
assert_eq!(inner.state, SocketState::Running);
|
||||||
|
|
||||||
gst_debug!(SOCKET_CAT, obj: &inner.element, "Trying to read data");
|
gst_debug!(SOCKET_CAT, obj: &inner.element, "Trying to read data");
|
||||||
let (len, time) = {
|
let (len, time) = {
|
||||||
|
@ -362,6 +447,8 @@ impl Stream for SocketStream {
|
||||||
buffer.set_dts(time);
|
buffer.set_dts(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Only ever poll the second again in Xms, using tokio-timer
|
||||||
|
|
||||||
Ok(Async::Ready(Some(buffer)))
|
Ok(Async::Ready(Some(buffer)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue