diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-12-01 09:21:42 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-12-01 09:28:33 +0200 |
commit | febcacdb5a60d37c2a56c9aad7b636be799940cd (patch) | |
tree | b04f92b4fb2125c6ee247e87a9f19fe8b34a9ff3 /build2/context.hxx | |
parent | 474d70d1dd7a60b5a0dccbe9c3ab1139a9ef31ac (diff) |
Terminate waiting threads if coming off failed load phase
In this case the build state may no longer be valid.
Diffstat (limited to 'build2/context.hxx')
-rw-r--r-- | build2/context.hxx | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/build2/context.hxx b/build2/context.hxx index c3e0595..5815f51 100644 --- a/build2/context.hxx +++ b/build2/context.hxx @@ -68,13 +68,22 @@ namespace build2 // process may pick up headers as they are being generated. As a result, we // either have everyone treat the external state as read-only or write-only. // + // There is also one more complication: if we are returning from a load + // phase that has failed, then the build state could be seriously messed up + // (things like scopes not being setup completely, etc). And once we release + // the lock, other threads that are waiting will start relying on this + // messed up state. So a load phase can mark the phase_mutex as failed in + // which case all currently blocked and future lock()/relock() calls return + // false. Note that in this case we still switch to the desired phase. See + // the phase_{lock,switch,unlock} implementations for details. + // class phase_mutex { public: // Acquire a phase lock potentially blocking (unless already in the // desired phase) until switching to the desired phase is possible. // - void + bool lock (run_phase); // Release the phase lock potentially allowing (unless there are other @@ -86,7 +95,7 @@ namespace build2 // Switch from one phase to another. Semantically, just unlock() followed // by lock() but more efficient. // - void + bool relock (run_phase unlock, run_phase lock); private: @@ -94,7 +103,11 @@ namespace build2 friend struct phase_unlock; friend struct phase_switch; - phase_mutex (): lc_ (0), mc_ (0), ec_ (0) {phase = run_phase::load;} + phase_mutex () + : fail_ (false), lc_ (0), mc_ (0), ec_ (0) + { + phase = run_phase::load; + } static phase_mutex instance; @@ -110,6 +123,9 @@ namespace build2 // is always changed to load (this is also the initial state). // mutex m_; + + bool fail_; + size_t lc_; size_t mc_; size_t ec_; @@ -201,7 +217,7 @@ namespace build2 struct phase_unlock { phase_unlock (bool unlock = true); - ~phase_unlock (); + ~phase_unlock () noexcept (false); phase_lock* l; }; @@ -212,7 +228,7 @@ namespace build2 struct phase_switch { explicit phase_switch (run_phase); - ~phase_switch (); + ~phase_switch () noexcept (false); run_phase o, n; }; |