mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 04:27:57 +00:00
Switch consensus crates to new futures (#3146)
* Switch consensus-common to new futures * Fix tests * More tests fixing * Fix Babe tests * Fix Babe tests
This commit is contained in:
committed by
Gavin Wood
parent
3a6a309d84
commit
b31dcdf342
@@ -33,7 +33,7 @@ pub enum Error {
|
||||
IoTerminated,
|
||||
/// Unable to schedule wakeup.
|
||||
#[display(fmt="Timer error: {}", _0)]
|
||||
FaultyTimer(tokio_timer::Error),
|
||||
FaultyTimer(std::io::Error),
|
||||
/// Error while working with inherent data.
|
||||
#[display(fmt="InherentData error: {}", _0)]
|
||||
InherentData(String),
|
||||
|
||||
@@ -106,8 +106,8 @@ pub trait ImportQueue<B: BlockT>: Send {
|
||||
///
|
||||
/// This method should behave in a way similar to `Future::poll`. It can register the current
|
||||
/// task and notify later when more actions are ready to be polled. To continue the comparison,
|
||||
/// it is as if this method always returned `Ok(Async::NotReady)`.
|
||||
fn poll_actions(&mut self, link: &mut dyn Link<B>);
|
||||
/// it is as if this method always returned `Poll::Pending`.
|
||||
fn poll_actions(&mut self, cx: &mut futures::task::Context, link: &mut dyn Link<B>);
|
||||
}
|
||||
|
||||
/// Hooks that the verification queue can use to influence the synchronization
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
use futures::{prelude::*, future::Executor, sync::mpsc};
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
use futures::{prelude::*, channel::mpsc, task::SpawnExt as _, task::Context, task::Poll};
|
||||
use runtime_primitives::{Justification, traits::{Block as BlockT, Header as HeaderT, NumberFor}};
|
||||
|
||||
use crate::error::Error as ConsensusError;
|
||||
@@ -34,15 +34,12 @@ pub struct BasicQueue<B: BlockT> {
|
||||
sender: mpsc::UnboundedSender<ToWorkerMsg<B>>,
|
||||
/// Results coming from the worker task.
|
||||
result_port: BufferedLinkReceiver<B>,
|
||||
/// Since we have to be in a tokio context in order to spawn background tasks, we first store
|
||||
/// the task to spawn here, then extract it as soon as we are in a tokio context.
|
||||
/// If `Some`, contains the task to spawn in the background. If `None`, the future has already
|
||||
/// been spawned.
|
||||
future_to_spawn: Option<Box<dyn Future<Item = (), Error = ()> + Send>>,
|
||||
/// If it isn't possible to spawn the future in `future_to_spawn` (which is notably the case in
|
||||
/// "no std" environment), we instead put it in `manual_poll`. It is then polled manually from
|
||||
/// `poll_actions`.
|
||||
manual_poll: Option<Box<dyn Future<Item = (), Error = ()> + Send>>,
|
||||
manual_poll: Option<Pin<Box<dyn Future<Output = ()> + Send>>>,
|
||||
/// A thread pool where the background worker is being run.
|
||||
pool: Option<futures::executor::ThreadPool>,
|
||||
}
|
||||
|
||||
impl<B: BlockT> BasicQueue<B> {
|
||||
@@ -65,11 +62,27 @@ impl<B: BlockT> BasicQueue<B> {
|
||||
finality_proof_import,
|
||||
);
|
||||
|
||||
let mut pool = futures::executor::ThreadPool::builder()
|
||||
.name_prefix("import-queue-worker-")
|
||||
.pool_size(1)
|
||||
.create()
|
||||
.ok();
|
||||
|
||||
let manual_poll;
|
||||
if let Some(pool) = &mut pool {
|
||||
// TODO: this expect() can be removed once
|
||||
// https://github.com/rust-lang-nursery/futures-rs/pull/1750 is merged and deployed
|
||||
pool.spawn(future).expect("ThreadPool can never fail to spawn tasks; QED");
|
||||
manual_poll = None;
|
||||
} else {
|
||||
manual_poll = Some(Box::pin(future) as Pin<Box<_>>);
|
||||
}
|
||||
|
||||
Self {
|
||||
sender: worker_sender,
|
||||
result_port,
|
||||
future_to_spawn: Some(Box::new(future)),
|
||||
manual_poll: None,
|
||||
manual_poll,
|
||||
pool,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,25 +112,17 @@ impl<B: BlockT> ImportQueue<B> for BasicQueue<B> {
|
||||
let _ = self.sender.unbounded_send(ToWorkerMsg::ImportFinalityProof(who, hash, number, finality_proof));
|
||||
}
|
||||
|
||||
fn poll_actions(&mut self, link: &mut dyn Link<B>) {
|
||||
// Try to spawn the future in `future_to_spawn`.
|
||||
if let Some(future) = self.future_to_spawn.take() {
|
||||
if let Err(err) = tokio_executor::DefaultExecutor::current().execute(future) {
|
||||
debug_assert!(self.manual_poll.is_none());
|
||||
self.manual_poll = Some(err.into_future());
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_actions(&mut self, cx: &mut Context, link: &mut dyn Link<B>) {
|
||||
// As a backup mechanism, if we failed to spawn the `future_to_spawn`, we instead poll
|
||||
// manually here.
|
||||
if let Some(manual_poll) = self.manual_poll.as_mut() {
|
||||
match manual_poll.poll() {
|
||||
Ok(Async::NotReady) => {}
|
||||
match Future::poll(Pin::new(manual_poll), cx) {
|
||||
Poll::Pending => {}
|
||||
_ => self.manual_poll = None,
|
||||
}
|
||||
}
|
||||
|
||||
self.result_port.poll_actions(link);
|
||||
self.result_port.poll_actions(cx, link);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +149,7 @@ impl<B: BlockT, V: 'static + Verifier<B>> BlockImportWorker<B, V> {
|
||||
block_import: BoxBlockImport<B>,
|
||||
justification_import: Option<BoxJustificationImport<B>>,
|
||||
finality_proof_import: Option<BoxFinalityProofImport<B>>,
|
||||
) -> (impl Future<Item = (), Error = ()> + Send, mpsc::UnboundedSender<ToWorkerMsg<B>>) {
|
||||
) -> (impl Future<Output = ()> + Send, mpsc::UnboundedSender<ToWorkerMsg<B>>) {
|
||||
let (sender, mut port) = mpsc::unbounded();
|
||||
|
||||
let mut worker = BlockImportWorker {
|
||||
@@ -167,12 +172,12 @@ impl<B: BlockT, V: 'static + Verifier<B>> BlockImportWorker<B, V> {
|
||||
}
|
||||
}
|
||||
|
||||
let future = futures::future::poll_fn(move || {
|
||||
let future = futures::future::poll_fn(move |cx| {
|
||||
loop {
|
||||
let msg = match port.poll() {
|
||||
Ok(Async::Ready(Some(msg))) => msg,
|
||||
Err(_) | Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
|
||||
Ok(Async::NotReady) => return Ok(Async::NotReady),
|
||||
let msg = match Stream::poll_next(Pin::new(&mut port), cx) {
|
||||
Poll::Ready(Some(msg)) => msg,
|
||||
Poll::Ready(None) => return Poll::Ready(()),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
};
|
||||
|
||||
match msg {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```no_run
|
||||
//! ```
|
||||
//! use substrate_consensus_common::import_queue::Link;
|
||||
//! # use substrate_consensus_common::import_queue::buffered_link::buffered_link;
|
||||
//! # use test_client::runtime::Block;
|
||||
@@ -28,12 +28,18 @@
|
||||
//! # let mut my_link = DummyLink;
|
||||
//! let (mut tx, mut rx) = buffered_link::<Block>();
|
||||
//! tx.blocks_processed(0, 0, vec![]);
|
||||
//! rx.poll_actions(&mut my_link); // Calls `my_link.blocks_processed(0, 0, vec![])`
|
||||
//!
|
||||
//! // Calls `my_link.blocks_processed(0, 0, vec![])` when polled.
|
||||
//! let _fut = futures::future::poll_fn(move |cx| {
|
||||
//! rx.poll_actions(cx, &mut my_link);
|
||||
//! std::task::Poll::Pending::<()>
|
||||
//! });
|
||||
//! ```
|
||||
//!
|
||||
|
||||
use futures::{prelude::*, sync::mpsc};
|
||||
use futures::{prelude::*, channel::mpsc};
|
||||
use runtime_primitives::traits::{Block as BlockT, NumberFor};
|
||||
use std::{pin::Pin, task::Context, task::Poll};
|
||||
use crate::import_queue::{Origin, Link, BlockImportResult, BlockImportError};
|
||||
|
||||
/// Wraps around an unbounded channel from the `futures` crate. The sender implements `Link` and
|
||||
@@ -120,10 +126,10 @@ impl<B: BlockT> BufferedLinkReceiver<B> {
|
||||
///
|
||||
/// This method should behave in a way similar to `Future::poll`. It can register the current
|
||||
/// task and notify later when more actions are ready to be polled. To continue the comparison,
|
||||
/// it is as if this method always returned `Ok(Async::NotReady)`.
|
||||
pub fn poll_actions(&mut self, link: &mut dyn Link<B>) {
|
||||
/// it is as if this method always returned `Poll::Pending`.
|
||||
pub fn poll_actions(&mut self, cx: &mut Context, link: &mut dyn Link<B>) {
|
||||
loop {
|
||||
let msg = if let Ok(Async::Ready(Some(msg))) = self.rx.poll() {
|
||||
let msg = if let Poll::Ready(Some(msg)) = Stream::poll_next(Pin::new(&mut self.rx), cx) {
|
||||
msg
|
||||
} else {
|
||||
break
|
||||
|
||||
@@ -75,7 +75,7 @@ pub trait Proposer<B: BlockT> {
|
||||
/// Error type which can occur when proposing or evaluating.
|
||||
type Error: From<Error> + ::std::fmt::Debug + 'static;
|
||||
/// Future that resolves to a committed proposal.
|
||||
type Create: IntoFuture<Item=B, Error=Self::Error>;
|
||||
type Create: Future<Output = Result<B, Self::Error>>;
|
||||
/// Create a proposal.
|
||||
fn propose(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user