void ScriptInterpreter::Stop(void)
{
+ assert(Application::IsMainThread());
+
{
boost::mutex::scoped_lock lock(m_Mutex);
m_CallAvailable.notify_all();
}
+ BOOST_FOREACH(const String& function, m_SubscribedFunctions) {
+ ScriptFunction::Unregister(function);
+ }
+
m_Thread.join();
}
}
}
+void ScriptInterpreter::ScriptFunctionThunk(const ScriptTask::Ptr& task,
+ const vector<Value>& arguments, const String& function)
+{
+ ScriptCall call;
+ call.Function = function;
+ call.Arguments = arguments;
+ call.Task = task;
+
+ {
+ boost::mutex::scoped_lock lock(m_Mutex);
+ m_Calls.push_back(call);
+ m_CallAvailable.notify_all();
+ }
+}
-void ScriptInterpreter::EnqueueCall(const ScriptCall& call)
+void ScriptInterpreter::SubscribeFunction(const String& name)
{
- boost::mutex::scoped_lock lock(m_Mutex);
- m_Calls.push_back(call);
- m_CallAvailable.notify_all();
+ 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::RegisterMethod(const String& name)
+void ScriptInterpreter::UnsubscribeFunction(const String& name)
{
- // TODO: implement
+ assert(Application::IsMainThread());
+
+ m_SubscribedFunctions.erase(name);
+ ScriptFunction::Unregister(name);
}
struct ScriptCall
{
- String Method;
- vector<String> Arguments;
+ String Function;
+ vector<Value> Arguments;
ScriptTask::Ptr Task;
};
~ScriptInterpreter(void);
- void EnqueueCall(const ScriptCall& call);
-
void Start(void);
void Stop(void);
protected:
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:
boost::mutex m_Mutex;
deque<ScriptCall> m_Calls;
condition_variable m_CallAvailable;
+ set<String> m_SubscribedFunctions; /* Not protected by the mutex. */
+
boost::thread m_Thread;
void ThreadWorkerProc(void);
+
+ void ScriptFunctionThunk(const ScriptTask::Ptr& task,
+ const vector<Value>& arguments, const String& function);
};
}
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)
{
PyEval_AcquireLock();
(void) PyThreadState_Swap(m_ThreadState);
PyRun_SimpleString(script->GetCode().CStr());
- (void) PyThreadState_Swap(m_Language->GetMainThreadState());
+ (void) PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
+
+ SubscribeFunction("python::Test");
}
PythonInterpreter::~PythonInterpreter(void)
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);
- PyRun_SimpleString("import antigravity");
+ std::cout << "Received call for method '" << function << "'" << std::endl;
PyEval_ReleaseThread(m_ThreadState);
- call.Task->FinishResult(0);
+ task->FinishResult(0);
}
PythonInterpreter(const PythonLanguage::Ptr& language, const Script::Ptr& script);
~PythonInterpreter(void);
+ void RegisterFunction(const String& name, PyObject *function);
+ void UnregisterFunction(const String& name);
+
protected:
PythonLanguage::Ptr m_Language;
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);
};
}