From 1be6a9ca586970919555c8e227558f769a27d4bc Mon Sep 17 00:00:00 2001 From: elvez Date: Sun, 13 Aug 2006 14:20:04 +0000 Subject: [PATCH] - All policy-related errors should now be handled. I hope this is the last time I say this... git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@850 3ecf2c5c-341e-0410-92b4-d18e462d057c --- src/backend/concrete_simulation.cc | 34 ++++++++++++-- src/backend/concrete_simulation.hh | 5 +- src/backend/cpu_policies_gatekeeper.cc | 63 +++++++++++++++----------- src/backend/cpu_policies_gatekeeper.hh | 8 +++- src/backend/scheduler.cc | 2 +- src/backend/scheduler.hh | 3 +- src/text_simulation.cc | 23 ++++++++-- 7 files changed, 102 insertions(+), 36 deletions(-) diff --git a/src/backend/concrete_simulation.cc b/src/backend/concrete_simulation.cc index 05c7592..de78b49 100644 --- a/src/backend/concrete_simulation.cc +++ b/src/backend/concrete_simulation.cc @@ -155,11 +155,39 @@ ConcreteSimulation::get_history() } void -ConcreteSimulation::set_policy(CPUPolicy* p) +ConcreteSimulation::set_policy(CPUPolicy* p) throw(CPUPolicyException) { - _policy = p; + // NOTE: restoring of the previous policy is done here because I + // couldn't think of a clean way to do it + // inside activate_policy() + + try + { + CPUPoliciesGatekeeper::get_instance().activate_policy(&_history, p); + _policy = p; + } + catch(const CPUPolicyException& e1) + { + try + { + // this is a no-op if _policy is NULL + CPUPoliciesGatekeeper::get_instance().activate_policy(&_history, _policy); + } + catch(const CPUPolicyException& e2) + { + _policy = NULL; - CPUPoliciesGatekeeper::get_instance().activate_policy(&_history, p); + string msg = _("unable to change policy and to restore the previous: "); + msg += e2.what(); + + throw CPUPolicyException(msg); + } + + string msg = _("unable to change policy: "); + msg+= e1.what(); + + throw CPUPolicyException(msg); + } } diff --git a/src/backend/concrete_simulation.hh b/src/backend/concrete_simulation.hh index f72b27c..40c0ec9 100644 --- a/src/backend/concrete_simulation.hh +++ b/src/backend/concrete_simulation.hh @@ -49,7 +49,10 @@ namespace sgpem state get_state() const; - void set_policy(CPUPolicy*); + /** + \throw An instance of CPUPolicyException, \b not a derived class!!! + */ + void set_policy(CPUPolicy*) throw(CPUPolicyException); ConcreteHistory& get_history(); diff --git a/src/backend/cpu_policies_gatekeeper.cc b/src/backend/cpu_policies_gatekeeper.cc index 00225b8..839c6f9 100644 --- a/src/backend/cpu_policies_gatekeeper.cc +++ b/src/backend/cpu_policies_gatekeeper.cc @@ -90,46 +90,57 @@ CPUPoliciesGatekeeper::get_current_policy(History* history) throw(runtime_error) } void -CPUPoliciesGatekeeper::activate_policy(History *history, CPUPolicy* policy) +CPUPoliciesGatekeeper::activate_policy(History *history, CPUPolicy* policy) throw(UserInterruptException, MalformedPolicyException) { assert(history != NULL); ActiveIterator end = _active_policies.end(); ActiveIterator pos = _active_policies.find(history); - if (pos != end && pos->second != policy) - _active_policies[history]->deactivate(); + // deactivate the policy, if necessary + if (pos != end) + { + // nothing to do in this case + if(pos->second == policy) + return; + pos->second->deactivate(); + } + + // if policy is NULL, simply erase the entry and return, since we are sure the policy is + // not active due to the previous lines if(policy == NULL) { - _active_policies.erase(pos); + // this is a no-op if history is not a key used in the map + _active_policies.erase(history); return; } - if (pos == end || pos->second != policy) + try { - try - { - // policy->activate() needs already an active policy, because: - // * it calls the configure() method on the - // insert-your-favourite-scripting-language-here-policy - // * which in turn calls the configure() method in the - // code written by the user - // * which probably uses Simulation to get the _active_ C++ policy, - // so it can get its policy_parameters() - // ... so **DON'T** play Mr. Clever Dick and swap the following two - // lines in an optimization frenzy! Or the user policy WILL fail. - _active_policies[history] = policy; - policy->activate(); - } - catch(const CPUPolicyException& e) - { - std::cerr << e.what() << std::endl; - // See the comment above to understand why we do this - // in this way - _active_policies.erase(_active_policies.find(history)); - } + // policy->activate() needs already an active policy, because: + // * it calls the configure() method on the + // insert-your-favourite-scripting-language-here-policy + // * which in turn calls the configure() method in the + // code written by the user + // * which probably uses Simulation to get the _active_ C++ policy, + // so it can get its policy_parameters() + // ... so **DON'T** play Mr. Clever Dick and swap the following two + // lines in an optimization frenzy! Or the user policy WILL fail. + _active_policies[history] = policy; + policy->activate(); } + catch(const CPUPolicyException& e) + { + //std::cerr << e.what() << std::endl; + // See the comment above to understand why we do this + // in this way + _active_policies.erase(_active_policies.find(history)); + + // the caller need to know if it failed + throw; + } + } CPUPoliciesGatekeeper::CPUPoliciesGatekeeper() diff --git a/src/backend/cpu_policies_gatekeeper.hh b/src/backend/cpu_policies_gatekeeper.hh index eb0e1ac..f0464b8 100644 --- a/src/backend/cpu_policies_gatekeeper.hh +++ b/src/backend/cpu_policies_gatekeeper.hh @@ -35,6 +35,8 @@ namespace sgpem #include #include "singleton.hh" +#include "malformed_policy_exception.hh" +#include "user_interrupt_exception.hh" namespace sgpem { @@ -58,7 +60,11 @@ namespace sgpem CPUPolicy* get_current_policy(History* history) throw(std::runtime_error); - void activate_policy(History* history, CPUPolicy* policy); + /** + Associates policy with history. If an exception is thrown, the current associated + policy with this history (if there are any), is \b no more active, \b nor associated + */ + void activate_policy(History* history, CPUPolicy* policy) throw(UserInterruptException, MalformedPolicyException); private: CPUPoliciesGatekeeper(); //private constructor. diff --git a/src/backend/scheduler.cc b/src/backend/scheduler.cc index f248a86..030b9f8 100644 --- a/src/backend/scheduler.cc +++ b/src/backend/scheduler.cc @@ -640,7 +640,7 @@ try_to_run(unsigned int front, auto_ptr& next_snapshot) bool Scheduler::step_forward(ConcreteHistory& concrete_history, CPUPolicy& cpu_policy) - throw(UserInterruptException) + throw(UserInterruptException, MalformedPolicyException) { // Preconditions: assert (concrete_history.get_size() > 0); diff --git a/src/backend/scheduler.hh b/src/backend/scheduler.hh index f8e3c93..9f9d7be 100644 --- a/src/backend/scheduler.hh +++ b/src/backend/scheduler.hh @@ -32,6 +32,7 @@ namespace sgpem #include "cpu_policy.hh" #include "ready_queue.hh" #include "user_interrupt_exception.hh" +#include "malformed_policy_exception.hh" // Do not include full template definition here #include "singleton.hh" @@ -78,7 +79,7 @@ namespace sgpem \return false If the simulation has ended, true otherwise */ - bool step_forward(ConcreteHistory& history, CPUPolicy& cpu_policy) throw(UserInterruptException); + bool step_forward(ConcreteHistory& history, CPUPolicy& cpu_policy) throw(UserInterruptException, MalformedPolicyException); /** Returns the policy that will be used to generate the simulation at the next instant. diff --git a/src/text_simulation.cc b/src/text_simulation.cc index bc69ac8..ef662f3 100644 --- a/src/text_simulation.cc +++ b/src/text_simulation.cc @@ -374,7 +374,17 @@ TextSimulation::on_run(const Tokens& arguments) p_stderr(e.what()); p_stderr(_("\nSimulation is now stopped, and " "the current policy will be deactivated\n")); - Simulation::get_instance().set_policy(NULL); + try + { + Simulation::get_instance().set_policy(NULL); + } + catch(const CPUPolicyException& f) + { + // should never happen + p_stderr(_("FATAL ERROR: unable to deactivate the policy: ")); + p_stderr(f.what()); + abort(); + } } catch (const NullPolicyException& e) { @@ -666,8 +676,8 @@ TextSimulation::on_set(const Tokens& arguments) vector policies = (*it)->get_avail_policies(); for (CPUPolicyIt it = policies.begin(); it != policies.end(); ++it) { - if (policy == 0) - Simulation::get_instance().set_policy(*it); + if (policy == 0) + Simulation::get_instance().set_policy(*it); --policy; } @@ -680,6 +690,13 @@ TextSimulation::on_set(const Tokens& arguments) { p_stderr(_("ERROR: invalid unsigned integer or not a valid policy index\n")); } + catch (const CPUPolicyException& e) + { + p_stderr(_("ERROR: ")); + p_stderr(e.what()); + p_stderr("\n"); + } + } else if (attr == "CONTINUOUS") {