From e0a743849551cfe2db036afef7f2ccbe9815a385 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 9 Dec 2011 16:28:14 -0500 Subject: [PATCH] support for unmanaged threads (e.g. started from python) --- include/mitsuba/core/thread.h | 9 ++++++++ src/libcore/thread.cpp | 41 +++++++++++++++++++++++++---------- src/libpython/core.cpp | 4 +++- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/include/mitsuba/core/thread.h b/include/mitsuba/core/thread.h index e1aad24d..64cadebd 100644 --- a/include/mitsuba/core/thread.h +++ b/include/mitsuba/core/thread.h @@ -153,6 +153,15 @@ public: /// Initialize Mitsuba's threading system for simultaneous use of OpenMP static void initializeOpenMP(size_t threadCount); + /** + * \brief Register an unmanaged thread with Mitsuba (i.e. one that + * doesn't derive from \c mitsuba::Thread) + * + * Should be called from the thread in question. The function returns + * a Mitsuba handle to the thread + */ + static Thread *registerUnmanagedThread(const std::string &name); + MTS_DECLARE_CLASS() protected: /// Virtual destructor diff --git a/src/libcore/thread.cpp b/src/libcore/thread.cpp index ca4c3ee2..be88c441 100644 --- a/src/libcore/thread.cpp +++ b/src/libcore/thread.cpp @@ -82,18 +82,18 @@ protected: virtual ~MainThread() { } }; -class OpenMPThread : public Thread { +class UnmanagedThread : public Thread { public: - OpenMPThread(int threadIdx) - : Thread(formatString("omp%i", threadIdx)) { } + UnmanagedThread(const std::string &name) + : Thread(name) { } virtual void run() { - Log(EError, "The OpenMP thread is already running!"); + Log(EError, "The unmanaged thread is already running!"); } MTS_DECLARE_CLASS() protected: - virtual ~OpenMPThread() { } + virtual ~UnmanagedThread() { } }; @@ -331,12 +331,28 @@ void Thread::staticInitialization() { } -static std::vector __ompThreads; +static std::vector __unmanagedThreads; + +Thread *Thread::registerUnmanagedThread(const std::string &name) { + Thread *thread = getThread(); + if (!thread) { + thread = new UnmanagedThread(name); + thread->m_running = false; + thread->m_thread = pthread_self(); + thread->m_joinMutex = new Mutex(); + thread->m_joined = false; + thread->incRef(); + m_self->set(thread); + #pragma omp critical + __unmanagedThreads.push_back((UnmanagedThread *) thread); + } + return thread; +} void Thread::staticShutdown() { - for (size_t i=0; i<__ompThreads.size(); ++i) - __ompThreads[i]->decRef(); - __ompThreads.clear(); + for (size_t i=0; i<__unmanagedThreads.size(); ++i) + __unmanagedThreads[i]->decRef(); + __unmanagedThreads.clear(); getThread()->m_running = false; m_self->set(NULL); delete m_self; @@ -385,7 +401,8 @@ void Thread::initializeOpenMP(size_t threadCount) { if (!thread) { #pragma omp critical { - thread = new OpenMPThread(counter); + thread = new UnmanagedThread( + formatString("omp%i", counter)); #if MTS_BROKEN_OPENMP == 1 __threadID.set(counter); #endif @@ -400,7 +417,7 @@ void Thread::initializeOpenMP(size_t threadCount) { thread->incRef(); m_self->set(thread); #pragma omp critical - __ompThreads.push_back((OpenMPThread *) thread); + __unmanagedThreads.push_back((UnmanagedThread *) thread); } } } @@ -412,5 +429,5 @@ Thread::~Thread() { MTS_IMPLEMENT_CLASS(Thread, true, Object) MTS_IMPLEMENT_CLASS(MainThread, false, Thread) -MTS_IMPLEMENT_CLASS(OpenMPThread, false, Thread) +MTS_IMPLEMENT_CLASS(UnmanagedThread, false, Thread) MTS_NAMESPACE_END diff --git a/src/libpython/core.cpp b/src/libpython/core.cpp index 8d2233d1..3abf6268 100644 --- a/src/libpython/core.cpp +++ b/src/libpython/core.cpp @@ -485,12 +485,14 @@ void export_core() { .def("getFileResolver", &Thread::getFileResolver, BP_RETURN_VALUE) .def("getThread", &Thread::getThread, BP_RETURN_VALUE) .def("isRunning", &Thread::isRunning) + .def("registerUnmanagedThread", &Thread::registerUnmanagedThread, BP_RETURN_VALUE) .def("sleep", &Thread::sleep) .def("detach", &Thread::detach) .def("join", &Thread::join) .def("start", &Thread::start) .staticmethod("sleep") - .staticmethod("getThread"); + .staticmethod("getThread") + .staticmethod("registerUnmanagedThread"); BP_SETSCOPE(Thread_class); bp::enum_("EThreadPriority")