+#include <stdexcept>
+#include <xbt/log.h>
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(thrd);
+
+#include "misc.h"
+#include "msg_thread.h"
+
+msg_thread::msg_thread()
+ : started(false)
+ , thread(NULL)
+ , thread_name("msg_thread")
+{
+}
+
+msg_thread::msg_thread(const char* name)
+ : started(false)
+ , thread(NULL)
+ , thread_name(name)
+{
+}
+
+msg_thread::~msg_thread()
+{
+ if (thread)
+ throw std::logic_error("trying to destroy running thread");
+}
+
+void msg_thread::start()
+{
+ mutex.acquire();
+ if (started)
+ throw std::logic_error("thread was already started");
+ XBT_DEBUG("launch \"%s\"", thread_name.c_str());
+ thread = MSG_process_create(thread_name.c_str(),
+ msg_thread::start_wrapper,
+ this, MSG_host_self());
+ started = true;
+ mutex.release();
+}
+
+void msg_thread::wait()
+{
+ mutex.acquire();
+ if (!started)
+ throw std::logic_error("trying to wait a thread that was not started");
+ while (thread) {
+ XBT_DEBUG("waiting for \"%s\" to terminate",
+ thread_name.c_str());
+ cond.wait(mutex);
+ }
+ mutex.release();
+}
+
+int msg_thread::start_wrapper(int, char* [])
+{
+ msg_thread* self;
+ self = static_cast<msg_thread*>(MSG_process_get_data(MSG_process_self()));
+ XBT_DEBUG("\"%s\" started", self->thread_name.c_str());
+ self->run();
+
+ XBT_DEBUG("terminate \"%s\"", self->thread_name.c_str());
+ self->mutex.acquire();
+ self->thread = NULL;
+ self->cond.signal();
+ self->mutex.release();
+ return 0;
+}