///
/// Called from the Executor when a Node completes.
///
/// A `result` value of `None` indicates that the Node was found to be clean, and its previous
/// result should be used. This special case exists to avoid 1) cloning the result to call this
/// method, and 2) comparing the current/previous results unnecessarily.
///
Called from the Executor when a Node completes.
A `result` value of `None` indicates that the Node was found to be clean, and its previous
result should be used. This special case exists to avoid 1) cloning the result to call this
method, and 2) comparing the current/previous results unnecessarily.
Called from the Executor when a Node completes . A ` result ` value of ` None ` indicates that the Node was found to be clean and its previous result should be used . This special case exists to avoid 1 ) cloning the result to call this method and 2 ) comparing the current / previous results unnecessarily .
pub(crate) fn complete(
    &self,
    context: &N::Context,
    result_run_token: RunToken,
    dep_generations: Vec<Generation>,
    result: Option<Result<N::Item, N::Error>>,
    has_uncacheable_deps: bool,
    has_weak_deps: bool,
  ) {
    let mut state = self.state.lock();
    // We care about exactly one case: a Running state with the same run_token. All other states
    // represent various (legal) race conditions. See `RunToken`'s docs for more information.
    match *state {
      EntryState::Running { run_token, .. } if result_run_token == run_token => {}
      _ => {
        // We care about exactly one case: a Running state with the same run_token. All other states
        // represent various (legal) race conditions.
        trace!(
          "Not completing node {:?} because it was invalidated.",
          self.node
        );
      }
    }
    *state = match mem::replace(&mut *state, EntryState::initial()) {
      EntryState::Running {
        run_token,
        waiters,
        mut generation,
        mut previous_result,
        ..
      } => {
        match result {
          Some(Err(e)) => {
            if let Some(previous_result) = previous_result.as_mut() {
              previous_result.dirty();
            }
            self.notify_waiters(waiters, Err(e));
            EntryState::NotStarted {
              run_token: run_token.next(),
              generation,
              previous_result,
            }
          }
          Some(Ok(result)) => {
            let next_result: EntryResult<N> = if !self.node.cacheable() {
              EntryResult::Uncacheable(result, context.session_id().clone())
            } else if has_weak_deps {
              EntryResult::Dirty(result)
            } else if has_uncacheable_deps {
              EntryResult::UncacheableDependencies(result)
            } else {
              EntryResult::Clean(result)
            };
            // If the new result does not match the previous result, the generation increments.
            if Some(next_result.as_ref()) != previous_result.as_ref().map(EntryResult::as_ref) {
              // Node was re-executed (ie not cleaned) and had a different result value.
              generation = generation.next()
            };
            self.notify_waiters(waiters, Ok((next_result.as_ref().clone(), generation)));
            EntryState::Completed {
              result: next_result,
              pollers: Vec::new(),
              dep_generations,
              run_token,
              generation,
            }
          }
          None => {
            // Node was clean.
            // NB: The `expect` here avoids a clone and a comparison: see the method docs.
            let mut result =
              previous_result.expect("A Node cannot be marked clean without a previous result.");
            if has_uncacheable_deps {
              result.uncacheable_deps();
            } else {
              result.clean();
            }
            self.notify_waiters(waiters, Ok((result.as_ref().clone(), generation)));
            EntryState::Completed {
              result,
              pollers: Vec::new(),
              dep_generations,
              run_token,
              generation,
            }
          }
        }
      }
      s => s,
    };
  }
pub ( crate ) fn complete ( & self , context : & N :: Context , result_run_token : RunToken , dep_generations : Vec < Generation > , result : Option < Result < N :: Item , N :: Error > > , has_uncacheable_deps : bool , has_weak_deps : bool , ) { let mut state = self . state . lock ( ) ; // We care about exactly one case: a Running state with the same run_token. All other states // represent various (legal) race conditions. See `RunToken`'s docs for more information. match * state { EntryState :: Running { run_token , .. } if result_run_token == run_token => { } _ => { // We care about exactly one case: a Running state with the same run_token. All other states // represent various (legal) race conditions. trace ! ( " " self node ) ; } } * state = match mem :: replace ( & mut * state , EntryState :: initial ( ) ) { EntryState :: Running { run_token , waiters , mut generation , mut previous_result , .. } => { match result { Some ( Err ( e ) ) => { if let Some ( previous_result ) = previous_result . as_mut ( ) { previous_result . dirty ( ) ; } self . notify_waiters ( waiters , Err ( e ) ) ; EntryState :: NotStarted { run_token : run_token . next ( ) , generation , previous_result , } } Some ( Ok ( result ) ) => { let next_result : EntryResult < N > = if ! self . node . cacheable ( ) { EntryResult :: Uncacheable ( result , context . session_id ( ) . clone ( ) ) } else if has_weak_deps { EntryResult :: Dirty ( result ) } else if has_uncacheable_deps { EntryResult :: UncacheableDependencies ( result ) } else { EntryResult :: Clean ( result ) } ; // If the new result does not match the previous result, the generation increments. if Some ( next_result . as_ref ( ) ) != previous_result . as_ref ( ) . map ( EntryResult :: as_ref ) { // Node was re-executed (ie not cleaned) and had a different result value. generation = generation . next ( ) } ; self . notify_waiters ( waiters , Ok ( ( next_result . as_ref ( ) . clone ( ) , generation ) ) ) ; EntryState :: Completed { result : next_result , pollers : Vec :: new ( ) , dep_generations , run_token , generation , } } None => { // Node was clean. // NB: The `expect` here avoids a clone and a comparison: see the method docs. let mut result = previous_result . expect ( " " ) ; if has_uncacheable_deps { result . uncacheable_deps ( ) ; } else { result . clean ( ) ; } self . notify_waiters ( waiters , Ok ( ( result . as_ref ( ) . clone ( ) , generation ) ) ) ; EntryState :: Completed { result , pollers : Vec :: new ( ) , dep_generations , run_token , generation , } } } } s => s , } ; }
Called from the Executor when a Node completes.
Called from the Executor when a Node completes .
&self
context
&N::Context
result_run_token
RunToken
dep_generations
Vec<Generation>
result
Option<Result<N::Item, N::Error>>
has_uncacheable_deps
bool
has_weak_deps
bool