aboutsummaryrefslogtreecommitdiff
path: root/build2/target
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-02-10 08:15:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-02-13 12:42:42 +0200
commitabccaf9596461215fce0e32322133fb6c39be44f (patch)
tree3fc16a6e6142d65e6b47ae686ab845cc164478cc /build2/target
parentbcb2a89e111a918a48a132a2a29e0c26d724591d (diff)
Implement parallel error propagation, keep_going mode
Keep going is the default but there is now the -s|--serial-stop that makes the driver run serially and stop at first error. Also fix some lockups, other minor improvements/features.
Diffstat (limited to 'build2/target')
-rw-r--r--build2/target43
1 files changed, 29 insertions, 14 deletions
diff --git a/build2/target b/build2/target
index e709395..2e13e69 100644
--- a/build2/target
+++ b/build2/target
@@ -64,13 +64,16 @@ namespace build2
// Recipe.
//
// The returned target state is normally changed or unchanged. If there is
- // an error, then the recipe should throw rather than returning failed.
+ // an error, then the recipe should throw failed rather than returning (this
+ // is the only exception that a recipe can throw).
//
// The return value of the recipe is used to update the target state. If it
// is target_state::group then the target's state is the group's state.
//
- // The recipe can also return postponed. In this case the target state is
- // set to unknown but the postponed state is propagated to the caller.
+ // The recipe may also return postponed in which case the target state is
+ // assumed to be unchanged (normally this means a prerequisite was postponed
+ // and while the prerequisite will be re-examined via another dependency,
+ // this target is done).
//
// Note that max size for the "small capture optimization" in std::function
// ranges (in pointer sizes) from 0 (GCC prior to 5) to 2 (GCC 5) to 6 (VC
@@ -401,13 +404,7 @@ namespace build2
// Target state.
//
- protected:
- friend target_state execute_impl (action, target&);
-
- target_state state_;
-
public:
-
// Atomic task count that is used during execution to (atomically) track a
// subset of the target's state as well as the number of its sub-tasks
// (execution of prerequisites).
@@ -429,16 +426,17 @@ namespace build2
mutable atomic_count task_count;
// Return the "stapshot" of the target state. That is, unless the target
- // has been executed, its state can change asynchronously.
+ // has been executed, its state can change asynchronously. If fail is
+ // true then translate target_state::failed to the failed exception.
//
target_state
- atomic_state () const;
+ atomic_state (bool fail = true) const;
// During execution this function can only be called if we have observed
// (synchronization-wise) that this target has been executed.
//
target_state
- synchronized_state () const;
+ synchronized_state (bool fail = true) const;
// Number of direct targets that depend on this target in the current
// action. It is incremented during the match phase and then decremented
@@ -455,6 +453,17 @@ namespace build2
//
atomic_count dependents;
+ protected:
+ friend target_state execute_impl (action, target&) noexcept;
+
+ target_state state_;
+
+ // Return fail-untranslated (but group-translated) state assuming the
+ // target is synchronized.
+ //
+ target_state
+ state () const;
+
// Auxilary data storage.
//
public:
@@ -530,6 +539,13 @@ namespace build2
void
recipe (action_type, recipe_type);
+ // After the recipe has been set (and target synchronized), check if the
+ // target is known to be unchanged. Used for various optimizations during
+ // search & match.
+ //
+ bool
+ unchanged () {return state () == target_state::unchanged;}
+
private:
recipe_type recipe_;
@@ -1181,8 +1197,7 @@ namespace build2
// much we can do here except detect the case where the target was
// changed on this run.
//
- return mt < mp || (mt == mp &&
- synchronized_state () == target_state::changed);
+ return mt < mp || (mt == mp && state () == target_state::changed);
}
protected: