summaryrefslogtreecommitdiff
path: root/src/MTS_Thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/MTS_Thread.cpp')
-rw-r--r--src/MTS_Thread.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/src/MTS_Thread.cpp b/src/MTS_Thread.cpp
new file mode 100644
index 0000000..3537731
--- /dev/null
+++ b/src/MTS_Thread.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2015 by Multi-Tech Systems
+ *
+ * This file is part of libmts.
+ *
+ * libmts is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libmts is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libmts. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <mts/MTS_Thread.h>
+#include <mts/MTS_Logger.h>
+#include <new>
+#include <cassert>
+
+using namespace MTS;
+
+Thread::Thread(const std::string& name, bool managed)
+: m_pThread(NULL)
+, m_sName(name)
+, m_bManaged(managed)
+, m_bComplete(true)
+, m_bCanceled(true)
+{
+ printConfig("Thread| %s()", getName().c_str());
+ m_apThreadLock.reset(new Lock());
+ m_apStateLock.reset(new Lock());
+ m_apCompleteCondition.reset(m_apStateLock->createCondition());
+}
+
+Thread::~Thread() {
+ m_bCanceled = true;
+ Thread::stop();
+ m_apCompleteCondition.reset();
+ m_apStateLock.reset();
+ m_apThreadLock.reset();
+ printConfig("Thread| %s - deconstructed", getName().c_str());
+}
+
+void Thread::sleep(uint32_t millis) {
+#ifdef WIN32
+ Sleep(millis);
+#else
+ Lock lock;
+ Condition* condition = lock.createCondition();
+ lock.lock();
+ condition->wait(millis);
+ lock.unlock();
+ delete condition;
+#endif
+}
+
+const std::string& Thread::getName() const {
+ return m_sName;
+}
+
+void Thread::start() {
+ m_apThreadLock->lock();
+ try {
+ if (m_pThread == NULL) {
+ reset();
+#ifdef WIN32
+ m_pThread = CreateThread(NULL, 0, &doInBackground, this, 0, NULL);
+#else
+ m_pThread = new (std::nothrow) pthread_t;
+ if (m_pThread != NULL) {
+ const int result = pthread_create(m_pThread, NULL,
+ &doInBackground, this);
+ assert(result == 0);
+ if (result != 0) {
+ delete m_pThread;
+ m_pThread = NULL;
+ }
+ }
+
+#endif
+ assert(m_pThread != NULL);
+ if (m_pThread != NULL) {
+ printConfig("Thread| %s - started (%p)",
+ getName().c_str(), m_pThread);
+ } else {
+ printWarning("Thread| Failed to start runnable %s",
+ getName().c_str());
+ m_apStateLock->lock();
+ m_bCanceled = true;
+ m_bComplete = true;
+ m_apStateLock->unlock();
+ }
+ }
+ } catch (...) {
+ printWarning("Thread| Failed to start runnable %s", getName().c_str());
+ assert(false);
+ }
+ m_apThreadLock->unlock();
+}
+
+void Thread::stop() {
+ m_apThreadLock->lock();
+ cancel();
+ if (m_pThread != NULL) {
+ wait(1500);
+
+#ifdef WIN32
+ if (!isDone()) {
+ TerminateThread(m_pThread, 1);
+ printConfig("Thread| %s - terminated", getName().c_str());
+ }
+ const BOOL ok = CloseHandle(m_pThread);
+ assert(ok);
+#else
+ if (!isDone()) {
+ printConfig("Thread| %s - terminated", getName().c_str());
+ }
+ delete m_pThread;
+#endif
+ m_pThread = NULL;
+ } else if (!isDone()) {
+ done();
+ }
+ m_apThreadLock->unlock();
+}
+
+void Thread::wait() {
+ m_apStateLock->lock();
+ if (!m_bComplete) {
+ m_apCompleteCondition->wait();
+ }
+ m_apStateLock->unlock();
+}
+
+void Thread::wait(uint32_t millis) {
+ m_apStateLock->lock();
+ if (!m_bComplete) {
+ m_apCompleteCondition->wait(millis);
+ }
+ m_apStateLock->unlock();
+}
+
+bool Thread::isAlive() const {
+ bool result = false;
+ m_apThreadLock->lock();
+ result = (m_pThread != NULL);
+ m_apThreadLock->unlock();
+ return result;
+}
+
+bool Thread::isCanceled() const {
+ bool result = false;
+ m_apStateLock->lock();
+ result = m_bCanceled;
+ m_apStateLock->unlock();
+ return result;
+}
+
+void Thread::cancel() {
+ m_apStateLock->lock();
+ if (!m_bCanceled) {
+ m_bCanceled = true;
+ printConfig("Thread| %s - cancelled", getName().c_str());
+ }
+ m_apStateLock->unlock();
+}
+
+bool Thread::isDone() const {
+ bool result = false;
+ m_apStateLock->lock();
+ result = m_bComplete;
+ m_apStateLock->unlock();
+ return result;
+}
+
+void Thread::done() {
+ m_apStateLock->lock();
+ m_bComplete = true;
+ m_apCompleteCondition->signal();
+ printConfig("Thread| %s - done", getName().c_str());
+ m_apStateLock->unlock();
+}
+
+void Thread::reset() {
+ m_apStateLock->lock();
+ m_bCanceled = false;
+ m_bComplete = false;
+ m_apStateLock->unlock();
+}
+
+bool Thread::isManaged() const {
+ return m_bManaged;
+}
+
+#ifdef WIN32
+DWORD WINAPI Thread::doInBackground(__in LPVOID parameter) {
+#else
+void* Thread::doInBackground(void* parameter) {
+#endif
+
+ Thread* runnable = static_cast<Thread*>(parameter);
+ assert(runnable != NULL);
+ if (runnable != NULL) {
+ printConfig("Thread| %s - initializing\n", runnable->getName().c_str());
+ try {
+ runnable->run();
+ } catch (...) {
+ printWarning("Thread| exception caught while running %s",
+ runnable->getName().c_str());
+ }
+ printConfig("Thread| %s - finalizing", runnable->getName().c_str());
+ bool managed = runnable->isManaged();
+ runnable->done();
+ if (!managed) {
+ printConfig("Thread| %s - deleted", runnable->getName().c_str());
+ delete runnable;
+ }
+ }
+ return 0;
+}
+