Properly shut down instances of the ScriptInterpreter class.

This commit is contained in:
Gunnar Beutner 2013-02-14 15:39:53 +01:00
parent 74b122d430
commit d4afb4087d
3 changed files with 50 additions and 20 deletions

View File

@ -57,6 +57,10 @@ void Script::SpawnInterpreter(void)
{ {
Logger::Write(LogInformation, "base", "Reloading script '" + GetName() + "'"); Logger::Write(LogInformation, "base", "Reloading script '" + GetName() + "'");
if (m_Interpreter)
m_Interpreter->Stop();
ScriptLanguage::Ptr language = ScriptLanguage::GetByName(GetLanguage()); ScriptLanguage::Ptr language = ScriptLanguage::GetByName(GetLanguage());
m_Interpreter = language->CreateInterpreter(GetSelf()); m_Interpreter = language->CreateInterpreter(GetSelf());
m_Interpreter->Start();
} }

View File

@ -22,19 +22,54 @@
using namespace icinga; using namespace icinga;
ScriptInterpreter::ScriptInterpreter(const Script::Ptr& script) ScriptInterpreter::ScriptInterpreter(const Script::Ptr& script)
: m_Thread(&ScriptInterpreter::ThreadWorkerProc, this) { }
ScriptInterpreter::~ScriptInterpreter(void)
{ {
m_Thread.detach(); Stop();
}
void ScriptInterpreter::Start(void)
{
/* We can't start the thread in the constructor because
* the worker thread might end up calling one of the virtual
* methods before the object is fully constructed. */
m_Thread = boost::thread(&ScriptInterpreter::ThreadWorkerProc, this);
}
void ScriptInterpreter::Stop(void)
{
{
boost::mutex::scoped_lock lock(m_Mutex);
if (m_Shutdown)
return;
m_Shutdown = true;
m_CallAvailable.notify_all();
}
m_Thread.join();
} }
void ScriptInterpreter::ThreadWorkerProc(void) void ScriptInterpreter::ThreadWorkerProc(void)
{ {
ScriptCall call; boost::mutex::scoped_lock lock(m_Mutex);
while (WaitForCall(&call)) for (;;) {
ProcessCall(call); while (m_Calls.empty() && !m_Shutdown)
m_CallAvailable.wait(lock);
if (m_Shutdown)
break;
ScriptCall call = m_Calls.front();
m_Calls.pop_front();
}
} }
void ScriptInterpreter::EnqueueCall(const ScriptCall& call) void ScriptInterpreter::EnqueueCall(const ScriptCall& call)
{ {
boost::mutex::scoped_lock lock(m_Mutex); boost::mutex::scoped_lock lock(m_Mutex);
@ -42,19 +77,6 @@ void ScriptInterpreter::EnqueueCall(const ScriptCall& call)
m_CallAvailable.notify_all(); m_CallAvailable.notify_all();
} }
bool ScriptInterpreter::WaitForCall(ScriptCall *call)
{
boost::mutex::scoped_lock lock(m_Mutex);
while (m_Calls.empty())
m_CallAvailable.wait(lock);
*call = m_Calls.front();
m_Calls.pop_front();
return true;
}
void ScriptInterpreter::RegisterMethod(const String& name) void ScriptInterpreter::RegisterMethod(const String& name)
{ {
// TODO: implement // TODO: implement

View File

@ -41,19 +41,23 @@ public:
typedef shared_ptr<ScriptInterpreter> Ptr; typedef shared_ptr<ScriptInterpreter> Ptr;
typedef weak_ptr<ScriptInterpreter> WeakPtr; typedef weak_ptr<ScriptInterpreter> WeakPtr;
~ScriptInterpreter(void);
void EnqueueCall(const ScriptCall& call); void EnqueueCall(const ScriptCall& call);
void Start(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 ScriptCall& call) = 0;
bool WaitForCall(ScriptCall *call);
void RegisterMethod(const String& name); void RegisterMethod(const String& name);
private: private:
boost::mutex m_Mutex; boost::mutex m_Mutex;
bool m_Shutdown;
deque<ScriptCall> m_Calls; deque<ScriptCall> m_Calls;
condition_variable m_CallAvailable; condition_variable m_CallAvailable;