// src/backend/python_policy.cc - Copyright 2005, 2006, University // of Padova, dept. of Pure and Applied // Mathematics // // This file is part of SGPEMv2. // // This is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // SGPEMv2 is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with SGPEMv2; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "python_policy.hh" #include #include using namespace sgpem; using namespace std; // WARNING : this class needs extensive and above all // *strong* exception checking / handling! PythonPolicy::PythonPolicy(const char* name) : _adapter(NULL), _adapter_dict(NULL), _lock(NULL), _name(name) { PyObject* pLoadmeStr = PyString_FromString(name); PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr); Py_DECREF(pLoadmeStr); if( !pUserPolicyModule ) { PyErr_Print(); // Error in import // FIXME : don't exit abruptly, but fall back gracefully exit(-1); } // Dictionary with defined ``symbols'' for .pyc file PyObject* pUserPolicyDict = PyModule_GetDict(pUserPolicyModule); assert(pUserPolicyDict); // Loads ScriptAdapter module and get its dictionary pLoadmeStr = PyString_FromString("ScriptAdapter"); PyObject* pScriptAdapterModule = PyImport_Import(pLoadmeStr); Py_DECREF(pLoadmeStr); assert(pScriptAdapterModule); _adapter_dict = PyModule_GetDict(pScriptAdapterModule); assert(_adapter_dict); // We want to keep a reference to it even if we decref // its containing module Py_INCREF(_adapter_dict); // Now takes the user-defined policy class from pUserPolicyDict PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, name); assert(pPolicyClass); // FIXME needs stricter checking and exception throwing // Save a reference to the global lock _lock = PyDict_GetItemString(_adapter_dict, "_g_mutex"); assert(_lock); // Creates a new object of type ScriptAdapter : // takes init function from ScriptAdapter class PyObject* pAdapterClass = PyDict_GetItemString(_adapter_dict, "ScriptAdapter"); PyObject* pAdapterCtorParam = PyTuple_New(1); Py_INCREF(pPolicyClass); // PyTuple_SetItem steals a reference PyTuple_SetItem(pAdapterCtorParam, 0, pPolicyClass); _adapter = PyInstance_New(pAdapterClass, pAdapterCtorParam, NULL); Py_DECREF(pAdapterCtorParam); assert(_adapter); Py_DECREF(pUserPolicyModule); Py_DECREF(pScriptAdapterModule); // And now, who's your daddy, huh? } PythonPolicy::~PythonPolicy() { if(_adapter) Py_DECREF(_adapter); if(_adapter_dict) Py_DECREF(_adapter_dict); } void PythonPolicy::configure() { PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL); Py_DECREF(retval); wait_unlock(); } void PythonPolicy::sort_queue(Scheduler::event event) const { PyObject* pEvent = PyInt_FromLong(event); PyObject* pMethodName = PyString_FromString("async_sort_queue"); PyObject* retval = PyObject_CallMethodObjArgs(_adapter, pMethodName, pEvent, NULL); if(!retval) PyErr_Print(); else Py_DECREF(retval); Py_DECREF(pMethodName); Py_DECREF(pEvent); wait_unlock(); } Glib::ustring PythonPolicy::get_description() const { return _name; } bool PythonPolicy::is_pre_emptive() const { PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL); Py_DECREF(retval); wait_unlock(); // Parse return value stored in global Python object retval = PyDict_GetItemString(_adapter_dict, "_ret_val"); return static_cast(PyInt_AsLong(retval)); } int PythonPolicy::get_time_slice() const { PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL); Py_DECREF(retval); wait_unlock(); // Parse return value stored in global Python object retval = PyDict_GetItemString(_adapter_dict, "_ret_val"); return static_cast(PyInt_AsLong(retval)); } void PythonPolicy::set_time_slice(const int&) { throw "The design is wrong, and I shouldn't be called."; } void PythonPolicy::wait_unlock() const { PyThreadState *_save; Py_UNBLOCK_THREADS sleep(2); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! // What we should really do here: /* do { enable python threads wait for some time... disable python threads ...check if user asked for interruption, reading a syncronized variable... ...if he has, break ...else: if the global lock is set: stay in this loop else: all's went okay, can exit loop } */ Py_BLOCK_THREADS }