fn run(&mut self, unit: &Unit, job: Job, cx: &Context<'_, '_>, scope: &Scope<'_>) {
        let id = JobId(self.next_id);
        self.next_id = self.next_id.checked_add(1).unwrap();

        info!("start {}: {:?}", id, unit);

        assert!(self.active.insert(id, unit.clone()).is_none());

        let messages = self.messages.clone();
        let fresh = job.freshness();
        let rmeta_required = cx.rmeta_required(unit);

        let doit = move |state: JobState<'_, '_>| {
            let mut sender = FinishOnDrop {
                messages: &state.messages,
                id,
                result: None,
            };
            sender.result = Some(job.run(&state));

            // If the `rmeta_required` wasn't consumed but it was set
            // previously, then we either have:
            //
            // 1. The `job` didn't do anything because it was "fresh".
            // 2. The `job` returned an error and didn't reach the point where
            //    it called `rmeta_produced`.
            // 3. We forgot to call `rmeta_produced` and there's a bug in Cargo.
            //
            // Ruling out the third, the other two are pretty common for 2
            // we'll just naturally abort the compilation operation but for 1
            // we need to make sure that the metadata is flagged as produced so
            // send a synthetic message here.
            if state.rmeta_required.get() && sender.result.as_ref().unwrap().is_ok() {
                state
                    .messages
                    .push(Message::Finish(state.id, Artifact::Metadata, Ok(())));
            }

            // Use a helper struct with a `Drop` implementation to guarantee
            // that a `Finish` message is sent even if our job panics. We
            // shouldn't panic unless there's a bug in Cargo, so we just need
            // to make sure nothing hangs by accident.
            struct FinishOnDrop<'a> {
                messages: &'a Queue<Message>,
                id: JobId,
                result: Option<CargoResult<()>>,
            }

            impl Drop for FinishOnDrop<'_> {
                fn drop(&mut self) {
                    let result = self
                        .result
                        .take()
                        .unwrap_or_else(|| Err(format_err!("worker panicked")));
                    self.messages
                        .push(Message::Finish(self.id, Artifact::All, result));
                }
            }
        };

        match fresh {
            Freshness::Fresh => {
                self.timings.add_fresh();
                // Running a fresh job on the same thread is often much faster than spawning a new
                // thread to run the job.
                doit(JobState {
                    id,
                    messages,
                    output: Some(&self.diag_dedupe),
                    rmeta_required: Cell::new(rmeta_required),
                    _marker: marker::PhantomData,
                });
            }
            Freshness::Dirty => {
                self.timings.add_dirty();
                scope.spawn(move |_| {
                    doit(JobState {
                        id,
                        messages: messages.clone(),
                        output: None,
                        rmeta_required: Cell::new(rmeta_required),
                        _marker: marker::PhantomData,
                    })
                });
            }
        }
    }
/// Executes a job.
///
/// Fresh jobs block until finished (which should be very fast!), Dirty
/// jobs will spawn a thread in the background and return immediately.
Executes a job.
Fresh jobs block until finished (which should be very fast!), Dirty
jobs will spawn a thread in the background and return immediately.
Executes a job . Fresh jobs block until finished ( which should be very fast! ) Dirty jobs will spawn a thread in the background and return immediately .
fn run(&mut self, unit: &Unit, job: Job, cx: &Context<'_, '_>, scope: &Scope<'_>) {
        let id = JobId(self.next_id);
        self.next_id = self.next_id.checked_add(1).unwrap();
        info!("start {}: {:?}", id, unit);
        assert!(self.active.insert(id, unit.clone()).is_none());
        let messages = self.messages.clone();
        let fresh = job.freshness();
        let rmeta_required = cx.rmeta_required(unit);
        let doit = move |state: JobState<'_, '_>| {
            let mut sender = FinishOnDrop {
                messages: &state.messages,
                id,
                result: None,
            };
            sender.result = Some(job.run(&state));
            // If the `rmeta_required` wasn't consumed but it was set
            // previously, then we either have:
            //
            // 1. The `job` didn't do anything because it was "fresh".
            // 2. The `job` returned an error and didn't reach the point where
            //    it called `rmeta_produced`.
            // 3. We forgot to call `rmeta_produced` and there's a bug in Cargo.
            //
            // Ruling out the third, the other two are pretty common for 2
            // we'll just naturally abort the compilation operation but for 1
            // we need to make sure that the metadata is flagged as produced so
            // send a synthetic message here.
            if state.rmeta_required.get() && sender.result.as_ref().unwrap().is_ok() {
                state
                    .messages
                    .push(Message::Finish(state.id, Artifact::Metadata, Ok(())));
            }
            // Use a helper struct with a `Drop` implementation to guarantee
            // that a `Finish` message is sent even if our job panics. We
            // shouldn't panic unless there's a bug in Cargo, so we just need
            // to make sure nothing hangs by accident.
            struct FinishOnDrop<'a> {
                messages: &'a Queue<Message>,
                id: JobId,
                result: Option<CargoResult<()>>,
            }
            impl Drop for FinishOnDrop<'_> {
                fn drop(&mut self) {
                    let result = self
                        .result
                        .take()
                        .unwrap_or_else(|| Err(format_err!("worker panicked")));
                    self.messages
                        .push(Message::Finish(self.id, Artifact::All, result));
                }
            }
        };
        match fresh {
            Freshness::Fresh => {
                self.timings.add_fresh();
                // Running a fresh job on the same thread is often much faster than spawning a new
                // thread to run the job.
                doit(JobState {
                    id,
                    messages,
                    output: Some(&self.diag_dedupe),
                    rmeta_required: Cell::new(rmeta_required),
                    _marker: marker::PhantomData,
                });
            }
            Freshness::Dirty => {
                self.timings.add_dirty();
                scope.spawn(move |_| {
                    doit(JobState {
                        id,
                        messages: messages.clone(),
                        output: None,
                        rmeta_required: Cell::new(rmeta_required),
                        _marker: marker::PhantomData,
                    })
                });
            }
        }
    }
fn run ( & mut self , unit : & Unit , job : Job , cx : & Context < ' _ , ' _ > , scope : & Scope < ' _ > ) { let id = JobId ( self . next_id ) ; self . next_id = self . next_id . checked_add ( 1 ) . unwrap ( ) ; info ! ( " " id unit ) ; assert ! ( self active insert ( id unit clone ( ) ) is_none ( ) ) ; let messages = self . messages . clone ( ) ; let fresh = job . freshness ( ) ; let rmeta_required = cx . rmeta_required ( unit ) ; let doit = move | state : JobState < ' _ , ' _ > | { let mut sender = FinishOnDrop { messages : & state . messages , id , result : None , } ; sender . result = Some ( job . run ( & state ) ) ; // If the `rmeta_required` wasn't consumed but it was set // previously, then we either have: // // 1. The `job` didn't do anything because it was "fresh". // 2. The `job` returned an error and didn't reach the point where //    it called `rmeta_produced`. // 3. We forgot to call `rmeta_produced` and there's a bug in Cargo. // // Ruling out the third, the other two are pretty common for 2 // we'll just naturally abort the compilation operation but for 1 // we need to make sure that the metadata is flagged as produced so // send a synthetic message here. if state . rmeta_required . get ( ) && sender . result . as_ref ( ) . unwrap ( ) . is_ok ( ) { state . messages . push ( Message :: Finish ( state . id , Artifact :: Metadata , Ok ( ( ) ) ) ) ; } // Use a helper struct with a `Drop` implementation to guarantee // that a `Finish` message is sent even if our job panics. We // shouldn't panic unless there's a bug in Cargo, so we just need // to make sure nothing hangs by accident. struct FinishOnDrop < ' a > { messages : & ' a Queue < Message > , id : JobId , result : Option < CargoResult < ( ) > > , } impl Drop for FinishOnDrop < ' _ > { fn drop ( & mut self ) { let result = self . result . take ( ) . unwrap_or_else ( | | Err ( format_err ! ( " " ) ) ) ; self . messages . push ( Message :: Finish ( self . id , Artifact :: All , result ) ) ; } } } ; match fresh { Freshness :: Fresh => { self . timings . add_fresh ( ) ; // Running a fresh job on the same thread is often much faster than spawning a new // thread to run the job. doit ( JobState { id , messages , output : Some ( & self . diag_dedupe ) , rmeta_required : Cell :: new ( rmeta_required ) , _marker : marker :: PhantomData , } ) ; } Freshness :: Dirty => { self . timings . add_dirty ( ) ; scope . spawn ( move | _ | { doit ( JobState { id , messages : messages . clone ( ) , output : None , rmeta_required : Cell :: new ( rmeta_required ) , _marker : marker :: PhantomData , } ) } ) ; } } }
Executes a job.
Executes a job .
&mut self
unit
&Unit
job
Job
cx
&Context<'_, '_>
scope
&Scope<'_>
&mut self
unit
&Unit
job
Job
cx
&Context<'_, '_>
scope
&Scope<'_>