From 45ef305a1b4732c95e56f72a91fd4c0e73e2cd8a Mon Sep 17 00:00:00 2001 From: tchernobog Date: Mon, 14 Aug 2006 14:28:41 +0000 Subject: [PATCH] - Incapsulate code so that the hack we previously used in CPUPoliciesGatekeeper isn't needed anymore - Now CPUPolicy has a callback method for scripting languages, but it is up to derived classes to take mutexes and set the value when needed (maybe we can improve this?) git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@862 3ecf2c5c-341e-0410-92b4-d18e462d057c --- plugins/pyloader/src/CPUPolicy.py | 2 +- plugins/pyloader/src/python_cpu_policy.cc | 38 +++++++++++++++++++++-- plugins/pyloader/src/python_cpu_policy.hh | 5 ++- plugins/pyloader/src/sgpem.i | 20 ++---------- src/backend/cpu_policies_gatekeeper.cc | 18 ++--------- src/backend/cpu_policy.cc | 22 +++++++++++++ src/backend/cpu_policy.hh | 14 ++++++++- 7 files changed, 80 insertions(+), 39 deletions(-) diff --git a/plugins/pyloader/src/CPUPolicy.py b/plugins/pyloader/src/CPUPolicy.py index 304f478..3204da3 100644 --- a/plugins/pyloader/src/CPUPolicy.py +++ b/plugins/pyloader/src/CPUPolicy.py @@ -97,7 +97,7 @@ class CPUPolicy: # # @return A sgpem::PolicyParameters instance def get_parameters(self): - return sgpem.CPUPolicy.get_active_policy().get_parameters() + return sgpem.CPUPolicy.callback_get_policy().get_parameters() ## @brief This function implements an in-place stable sort diff --git a/plugins/pyloader/src/python_cpu_policy.cc b/plugins/pyloader/src/python_cpu_policy.cc index fe40d47..c5ae4b8 100644 --- a/plugins/pyloader/src/python_cpu_policy.cc +++ b/plugins/pyloader/src/python_cpu_policy.cc @@ -29,6 +29,11 @@ using namespace std; #define WAIT_FOR (250000) + +// Static member data +Glib::StaticRecMutex PythonCPUPolicy::_mtx = GLIBMM_STATIC_REC_MUTEX_INIT; + + // WARNING : this class needs extensive and above all // *strong* exception checking / handling! @@ -89,19 +94,29 @@ PythonCPUPolicy::~PythonCPUPolicy() void PythonCPUPolicy::activate() throw(UserInterruptException, MalformedPolicyException) { + Glib::RecMutex::Lock lock(_mtx);; + set_callback_policy(const_cast(this)); + // FIXME write the rest, taking away code from constructor configure(); + + set_callback_policy(NULL); } void PythonCPUPolicy::deactivate() { + Glib::RecMutex::Lock lock(_mtx);; + set_callback_policy(const_cast(this)); + // FIXME See if some code has to be moved here from the // destructor, AFTER having written activate() _parameters.clear(); + + set_callback_policy(NULL); } @@ -109,16 +124,24 @@ PythonCPUPolicy::deactivate() void PythonCPUPolicy::configure() throw(UserInterruptException, MalformedPolicyException) { + Glib::RecMutex::Lock lock(_mtx);; + set_callback_policy(const_cast(this)); + PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL); Py_DECREF(retval); wait_unlock(); + + set_callback_policy(NULL); } void PythonCPUPolicy::sort_queue() const throw(UserInterruptException, MalformedPolicyException) -{ +{ + Glib::RecMutex::Lock lock(_mtx);; + set_callback_policy(const_cast(this)); + PyObject* retval = PyObject_CallMethod(_adapter, "async_sort_queue", NULL); // Do minimal debugging @@ -126,6 +149,8 @@ PythonCPUPolicy::sort_queue() const throw(UserInterruptException, MalformedPolic else Py_DECREF(retval); wait_unlock(); + + set_callback_policy(NULL); } @@ -145,6 +170,9 @@ PythonCPUPolicy::get_name() const bool PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException) { + Glib::RecMutex::Lock lock(_mtx);; + set_callback_policy(const_cast(this)); + PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL); Py_DECREF(retval); @@ -155,6 +183,8 @@ PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException, MalformedP assert(retval); bool ret = PyObject_IsTrue(retval); Py_DECREF(retval); + + set_callback_policy(NULL); return ret; } @@ -162,6 +192,9 @@ PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException, MalformedP int PythonCPUPolicy::get_time_slice() const throw(UserInterruptException, MalformedPolicyException) { + Glib::RecMutex::Lock lock(_mtx);; + set_callback_policy(const_cast(this)); + PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL); // Do minimal debugging @@ -176,6 +209,7 @@ PythonCPUPolicy::get_time_slice() const throw(UserInterruptException, MalformedP long tmp = PyInt_AsLong(retval); Py_DECREF(retval); + set_callback_policy(NULL); return tmp < 0 ? numeric_limits::max() : static_cast(tmp); } @@ -208,7 +242,7 @@ PythonCPUPolicy::wait_unlock() const throw(UserInterruptException, MalformedPoli PyEval_RestoreThread(_save); if(PyErr_Occurred() != NULL) - abort(); + abort(); throw UserInterruptException(_("User-defined policy is " "taking too long to terminate.")); diff --git a/plugins/pyloader/src/python_cpu_policy.hh b/plugins/pyloader/src/python_cpu_policy.hh index afb4cb8..d1f0497 100644 --- a/plugins/pyloader/src/python_cpu_policy.hh +++ b/plugins/pyloader/src/python_cpu_policy.hh @@ -24,6 +24,7 @@ #include "config.h" #include +#include #include #include @@ -63,7 +64,7 @@ namespace sgpem */ Glib::ustring get_description() const; - Glib::ustring get_name() const; + Glib::ustring get_name() const; /** \returns \c TRUE if the policy is preemptive. @@ -87,6 +88,8 @@ namespace sgpem void wait_unlock() const throw(UserInterruptException, MalformedPolicyException); static std::string get_exception_information(); + static Glib::StaticRecMutex _mtx; + PyObject* _upolicy_dict; PyObject* _adapter; diff --git a/plugins/pyloader/src/sgpem.i b/plugins/pyloader/src/sgpem.i index 36d5ff7..199a04c 100644 --- a/plugins/pyloader/src/sgpem.i +++ b/plugins/pyloader/src/sgpem.i @@ -67,26 +67,10 @@ namespace sgpem { virtual ~CPUPolicy() = 0; sgpem::PolicyParameters& get_parameters(); - %extend { - // Convenience function to get the current policy - static CPUPolicy* get_active_policy() - { - History& h = Simulation::get_instance().get_history(); - return CPUPoliciesGatekeeper::get_instance().get_current_policy(&h); - }; - } + static CPUPolicy* callback_get_policy() throw(std::runtime_error); }; - - // -------------------------------------------- - -// class PolicyParametersException : public std::runtime_error { -// public: -// PolicyParametersException(char* msg); -// %rename (__str__) what; -// virtual const char* what(); -// }; //~ class PolicyParametersException - // -------------------------------------------- + // -------------------------------------------- class PolicyParameters { public: diff --git a/src/backend/cpu_policies_gatekeeper.cc b/src/backend/cpu_policies_gatekeeper.cc index 839c6f9..c0c2fa9 100644 --- a/src/backend/cpu_policies_gatekeeper.cc +++ b/src/backend/cpu_policies_gatekeeper.cc @@ -118,25 +118,11 @@ CPUPoliciesGatekeeper::activate_policy(History *history, CPUPolicy* policy) thro 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(); + _active_policies[history] = policy; } 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; } diff --git a/src/backend/cpu_policy.cc b/src/backend/cpu_policy.cc index f42dfc7..6127bf9 100644 --- a/src/backend/cpu_policy.cc +++ b/src/backend/cpu_policy.cc @@ -22,6 +22,11 @@ using namespace std; using namespace sgpem; + +// Static member data +CPUPolicy* CPUPolicy::_callback_policy = NULL; + + CPUPolicy::~CPUPolicy() {} @@ -31,3 +36,20 @@ CPUPolicy::get_parameters() { return _parameters; } + + + +CPUPolicy* +CPUPolicy::callback_get_policy() throw(std::runtime_error) +{ + if(_callback_policy == NULL) + throw std::runtime_error("CPUPolicy::callback_get_policy() not used as a callback method. NULL ptr returned."); + return _callback_policy; +} + + +void +CPUPolicy::set_callback_policy(CPUPolicy* ptr) +{ + _callback_policy = ptr; +} diff --git a/src/backend/cpu_policy.hh b/src/backend/cpu_policy.hh index 6660836..5e90eca 100644 --- a/src/backend/cpu_policy.hh +++ b/src/backend/cpu_policy.hh @@ -30,6 +30,8 @@ #include "user_interrupt_exception.hh" #include "malformed_policy_exception.hh" +#include + namespace sgpem { class CPUPolicy; @@ -102,8 +104,18 @@ namespace sgpem */ PolicyParameters& get_parameters(); + /** This method is used only as a callback by scripting languages */ + static CPUPolicy* callback_get_policy() throw(std::runtime_error); + protected: - PolicyParameters _parameters; + PolicyParameters _parameters; + + static void set_callback_policy(CPUPolicy* ptr = NULL); + + private: + // Used by callback_get_policy: + static CPUPolicy* _callback_policy; + }; }//~ namespace sgpem