Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  async_executor.rs   Sprache: unbekannt

 
use std::{
    cell::Cell,
    future::Future,
    pin::Pin,
    ptr,
    task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
    thread,
    time::Duration,
};

use crate::Error;

const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
    // Cloning just returns a new no-op raw waker
    |_| NOOP_RAW_WAKER,
    // `wake` does nothing
    |_| {},
    // `wake_by_ref` does nothing
    |_| {},
    // Dropping does nothing as we don't allocate anything
    |_| {},
);
const NOOP_RAW_WAKER: RawWaker = RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE);

#[derive(Default)]
pub(crate) struct YieldOnce(bool);

impl Future for YieldOnce {
    type Output = ();

    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> {
        let flag = &mut std::pin::Pin::into_inner(self).0;
        if !*flag {
            *flag = true;
            Poll::Pending
        } else {
            Poll::Ready(())
        }
    }
}

/// Execute the futures and return when they are all done.
///
/// Here we use our own homebrew async executor since cc is used in the build
/// script of many popular projects, pulling in additional dependencies would
/// significantly slow down its compilation.
pub(crate) fn block_on<Fut1, Fut2>(
    mut fut1: Fut1,
    mut fut2: Fut2,
    has_made_progress: &Cell<bool>,
) -> Result<(), Error>
where
    Fut1: Future<Output = Result<(), Error>>,
    Fut2: Future<Output = Result<(), Error>>,
{
    // Shadows the future so that it can never be moved and is guaranteed
    // to be pinned.
    //
    // The same trick used in `pin!` macro.
    //
    // TODO: Once MSRV is bumped to 1.68, replace this with `std::pin::pin!`
    let mut fut1 = Some(unsafe { Pin::new_unchecked(&mut fut1) });
    let mut fut2 = Some(unsafe { Pin::new_unchecked(&mut fut2) });

    // TODO: Once `Waker::noop` stablised and our MSRV is bumped to the version
    // which it is stablised, replace this with `Waker::noop`.
    let waker = unsafe { Waker::from_raw(NOOP_RAW_WAKER) };
    let mut context = Context::from_waker(&waker);

    let mut backoff_cnt = 0;

    loop {
        has_made_progress.set(false);

        if let Some(fut) = fut2.as_mut() {
            if let Poll::Ready(res) = fut.as_mut().poll(&mut context) {
                fut2 = None;
                res?;
            }
        }

        if let Some(fut) = fut1.as_mut() {
            if let Poll::Ready(res) = fut.as_mut().poll(&mut context) {
                fut1 = None;
                res?;
            }
        }

        if fut1.is_none() && fut2.is_none() {
            return Ok(());
        }

        if !has_made_progress.get() {
            if backoff_cnt > 3 {
                // We have yielded at least three times without making'
                // any progress, so we will sleep for a while.
                let duration = Duration::from_millis(100 * (backoff_cnt - 3).min(10));
                thread::sleep(duration);
            } else {
                // Given that we spawned a lot of compilation tasks, it is unlikely
                // that OS cannot find other ready task to execute.
                //
                // If all of them are done, then we will yield them and spawn more,
                // or simply return.
                //
                // Thus this will not be turned into a busy-wait loop and it will not
                // waste CPU resource.
                thread::yield_now();
            }
        }

        backoff_cnt = if has_made_progress.get() {
            0
        } else {
            backoff_cnt + 1
        };
    }
}

[ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge