using namespace icinga;
ScriptInterpreter::ScriptInterpreter(const Script::Ptr& script)
- : m_Thread(&ScriptInterpreter::ThreadWorkerProc, this)
+{ }
+
+ScriptInterpreter::~ScriptInterpreter(void)
{
- m_Thread.detach();
+ Stop();
}
-void ScriptInterpreter::ThreadWorkerProc(void)
+void ScriptInterpreter::Start(void)
{
- ScriptCall call;
+ /* 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. */
- while (WaitForCall(&call))
- ProcessCall(call);
+ m_Thread = boost::thread(&ScriptInterpreter::ThreadWorkerProc, this);
}
-void ScriptInterpreter::EnqueueCall(const ScriptCall& call)
+void ScriptInterpreter::Stop(void)
{
- boost::mutex::scoped_lock lock(m_Mutex);
- m_Calls.push_back(call);
- m_CallAvailable.notify_all();
+ {
+ boost::mutex::scoped_lock lock(m_Mutex);
+
+ if (m_Shutdown)
+ return;
+
+ m_Shutdown = true;
+ m_CallAvailable.notify_all();
+ }
+
+ m_Thread.join();
}
-bool ScriptInterpreter::WaitForCall(ScriptCall *call)
+void ScriptInterpreter::ThreadWorkerProc(void)
{
boost::mutex::scoped_lock lock(m_Mutex);
- while (m_Calls.empty())
- m_CallAvailable.wait(lock);
+ for (;;) {
+ while (m_Calls.empty() && !m_Shutdown)
+ m_CallAvailable.wait(lock);
+
+ if (m_Shutdown)
+ break;
- *call = m_Calls.front();
- m_Calls.pop_front();
+ ScriptCall call = m_Calls.front();
+ m_Calls.pop_front();
+ }
+}
- return true;
+
+void ScriptInterpreter::EnqueueCall(const ScriptCall& call)
+{
+ boost::mutex::scoped_lock lock(m_Mutex);
+ m_Calls.push_back(call);
+ m_CallAvailable.notify_all();
}
void ScriptInterpreter::RegisterMethod(const String& name)
typedef shared_ptr<ScriptInterpreter> Ptr;
typedef weak_ptr<ScriptInterpreter> WeakPtr;
+ ~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;
- bool WaitForCall(ScriptCall *call);
-
void RegisterMethod(const String& name);
private:
boost::mutex m_Mutex;
+ bool m_Shutdown;
deque<ScriptCall> m_Calls;
condition_variable m_CallAvailable;