Implemented rudimentary function call forwarding for ScriptInterpreter objects.

This commit is contained in:
Gunnar Beutner 2013-02-14 16:43:58 +01:00
parent d3928a7e69
commit 8f2ce8e703
4 changed files with 74 additions and 19 deletions

View File

@ -40,6 +40,8 @@ void ScriptInterpreter::Start(void)
void ScriptInterpreter::Stop(void) void ScriptInterpreter::Stop(void)
{ {
assert(Application::IsMainThread());
{ {
boost::mutex::scoped_lock lock(m_Mutex); boost::mutex::scoped_lock lock(m_Mutex);
@ -50,6 +52,10 @@ void ScriptInterpreter::Stop(void)
m_CallAvailable.notify_all(); m_CallAvailable.notify_all();
} }
BOOST_FOREACH(const String& function, m_SubscribedFunctions) {
ScriptFunction::Unregister(function);
}
m_Thread.join(); m_Thread.join();
} }
@ -69,15 +75,35 @@ void ScriptInterpreter::ThreadWorkerProc(void)
} }
} }
void ScriptInterpreter::ScriptFunctionThunk(const ScriptTask::Ptr& task,
void ScriptInterpreter::EnqueueCall(const ScriptCall& call) const vector<Value>& arguments, const String& function)
{ {
boost::mutex::scoped_lock lock(m_Mutex); ScriptCall call;
m_Calls.push_back(call); call.Function = function;
m_CallAvailable.notify_all(); call.Arguments = arguments;
call.Task = task;
{
boost::mutex::scoped_lock lock(m_Mutex);
m_Calls.push_back(call);
m_CallAvailable.notify_all();
}
} }
void ScriptInterpreter::RegisterMethod(const String& name) void ScriptInterpreter::SubscribeFunction(const String& name)
{ {
// TODO: implement assert(Application::IsMainThread());
m_SubscribedFunctions.insert(name);
ScriptFunction::Ptr sf = boost::make_shared<ScriptFunction>(boost::bind(&ScriptInterpreter::ScriptFunctionThunk, this, _1, _2, name));
ScriptFunction::Register(name, sf);
}
void ScriptInterpreter::UnsubscribeFunction(const String& name)
{
assert(Application::IsMainThread());
m_SubscribedFunctions.erase(name);
ScriptFunction::Unregister(name);
} }

View File

@ -25,8 +25,8 @@ namespace icinga
struct ScriptCall struct ScriptCall
{ {
String Method; String Function;
vector<String> Arguments; vector<Value> Arguments;
ScriptTask::Ptr Task; ScriptTask::Ptr Task;
}; };
@ -43,17 +43,17 @@ public:
~ScriptInterpreter(void); ~ScriptInterpreter(void);
void EnqueueCall(const ScriptCall& call);
void Start(void); void Start(void);
void Stop(void); void Stop(void);
protected: protected:
ScriptInterpreter(const Script::Ptr& script); ScriptInterpreter(const Script::Ptr& script);
virtual void ProcessCall(const ScriptCall& call) = 0; virtual void ProcessCall(const String& function, const ScriptTask::Ptr& task,
const vector<Value>& arguments) = 0;
void RegisterMethod(const String& name); void SubscribeFunction(const String& name);
void UnsubscribeFunction(const String& name);
private: private:
boost::mutex m_Mutex; boost::mutex m_Mutex;
@ -61,9 +61,14 @@ private:
deque<ScriptCall> m_Calls; deque<ScriptCall> m_Calls;
condition_variable m_CallAvailable; condition_variable m_CallAvailable;
set<String> m_SubscribedFunctions; /* Not protected by the mutex. */
boost::thread m_Thread; boost::thread m_Thread;
void ThreadWorkerProc(void); void ThreadWorkerProc(void);
void ScriptFunctionThunk(const ScriptTask::Ptr& task,
const vector<Value>& arguments, const String& function);
}; };
} }

View File

@ -21,7 +21,8 @@
using namespace icinga; using namespace icinga;
PythonInterpreter::PythonInterpreter(const PythonLanguage::Ptr& language, const Script::Ptr& script) PythonInterpreter::PythonInterpreter(const PythonLanguage::Ptr& language,
const Script::Ptr& script)
: ScriptInterpreter(script), m_Language(language), m_ThreadState(NULL) : ScriptInterpreter(script), m_Language(language), m_ThreadState(NULL)
{ {
PyEval_AcquireLock(); PyEval_AcquireLock();
@ -31,9 +32,11 @@ PythonInterpreter::PythonInterpreter(const PythonLanguage::Ptr& language, const
(void) PyThreadState_Swap(m_ThreadState); (void) PyThreadState_Swap(m_ThreadState);
PyRun_SimpleString(script->GetCode().CStr()); PyRun_SimpleString(script->GetCode().CStr());
(void) PyThreadState_Swap(m_Language->GetMainThreadState()); (void) PyThreadState_Swap(NULL);
PyEval_ReleaseLock(); PyEval_ReleaseLock();
SubscribeFunction("python::Test");
} }
PythonInterpreter::~PythonInterpreter(void) PythonInterpreter::~PythonInterpreter(void)
@ -48,11 +51,27 @@ PythonInterpreter::~PythonInterpreter(void)
PyEval_ReleaseLock(); PyEval_ReleaseLock();
} }
void PythonInterpreter::ProcessCall(const ScriptCall& call) void PythonInterpreter::RegisterFunction(const String& name, PyObject *function)
{
SubscribeFunction(name);
Py_INCREF(function);
m_Functions[name] = function;
}
void PythonInterpreter::UnregisterFunction(const String& name)
{
UnsubscribeFunction(name);
m_Functions.erase(name);
}
void PythonInterpreter::ProcessCall(const String& function, const ScriptTask::Ptr& task,
const vector<Value>& arguments)
{ {
PyEval_AcquireThread(m_ThreadState); PyEval_AcquireThread(m_ThreadState);
PyRun_SimpleString("import antigravity"); std::cout << "Received call for method '" << function << "'" << std::endl;
PyEval_ReleaseThread(m_ThreadState); PyEval_ReleaseThread(m_ThreadState);
call.Task->FinishResult(0); task->FinishResult(0);
} }

View File

@ -37,11 +37,16 @@ public:
PythonInterpreter(const PythonLanguage::Ptr& language, const Script::Ptr& script); PythonInterpreter(const PythonLanguage::Ptr& language, const Script::Ptr& script);
~PythonInterpreter(void); ~PythonInterpreter(void);
void RegisterFunction(const String& name, PyObject *function);
void UnregisterFunction(const String& name);
protected: protected:
PythonLanguage::Ptr m_Language; PythonLanguage::Ptr m_Language;
PyThreadState *m_ThreadState; PyThreadState *m_ThreadState;
map<String, PyObject *> m_Functions;
virtual void ProcessCall(const ScriptCall& call); virtual void ProcessCall(const String& function, const ScriptTask::Ptr& task,
const vector<Value>& arguments);
}; };
} }