.. _program_listing_file__tmp_ws_src_ecl_core_ecl_threads_include_ecl_threads_thread_win.hpp: Program Listing for File thread_win.hpp ======================================= |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/ecl_core/ecl_threads/include/ecl/threads/thread_win.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /***************************************************************************** ** Ifdefs *****************************************************************************/ #ifndef ECL_THREADS_THREAD_WIN_HPP_ #define ECL_THREADS_THREAD_WIN_HPP_ /***************************************************************************** ** Platform Check *****************************************************************************/ #include #if defined(ECL_IS_WIN32) /***************************************************************************** ** Includes *****************************************************************************/ #include #include "thread_exceptions_pos.hpp" #include #include #include #include #include #include "priority_win.hpp" /***************************************************************************** ** Namespaces *****************************************************************************/ namespace ecl { namespace threads { /***************************************************************************** ** Interface [ThreadTask] *****************************************************************************/ class ECL_LOCAL ThreadTaskBase { public: virtual ~ThreadTaskBase() {}; protected: ThreadTaskBase(const Priority& priority) : priority_level(priority) {}; ecl::Priority priority_level; }; template class ECL_LOCAL ThreadTask : public ThreadTaskBase { public: ThreadTask(const F &f, const Priority &priority) : ThreadTaskBase(priority), function(f) { ecl_compile_time_concept_check(ecl::NullaryFunction); }; virtual ~ThreadTask() {}; static unsigned int EntryPoint(void *ptr_this) { ThreadTask< F, false > *ptr = static_cast< ThreadTask< F, false > * >(ptr_this); (ptr->function)(); return 0; } private: F function; }; template class ECL_LOCAL ThreadTask : public ThreadTaskBase { public: ThreadTask(const F &f, const Priority &priority) : ThreadTaskBase(priority), function(f.reference()) { ecl_compile_time_concept_check(ecl::NullaryFunction< typename F::type>); }; virtual ~ThreadTask() {}; static unsigned int EntryPoint(void *ptr_this) { ThreadTask< F, true > *ptr = static_cast< ThreadTask< F, true > * >(ptr_this); (ptr->function)(); return 0; } private: typename F::type &function; }; }; // namespace threads /***************************************************************************** ** Interface [Thread] *****************************************************************************/ class ecl_threads_PUBLIC Thread { public: Thread() : thread_handle(NULL), thread_task(NULL), has_started(false), join_requested(false) {} Thread(VoidFunction function, const Priority &priority = DefaultPriority, const long &stack_size = -1 ); Error start(VoidFunction function, const Priority &priority = DefaultPriority, const long &stack_size = -1 ); template Thread(void (C::*function)(), C &c, const Priority &priority = DefaultPriority, const long &stack_size = -1 ); template Error start(void (C::*function)(), C &c, const Priority &priority = DefaultPriority, const long &stack_size = -1 ); template Thread(const F &function, const Priority &priority = DefaultPriority, const long &stack_size = -1 ); template Error start(const F &function, const Priority &priority = DefaultPriority, const long &stack_size = -1 ); virtual ~Thread(); bool isRunning() { if ( thread_task == NULL ) { return false; } else { return true; } } void cancel(); void join(); private: HANDLE thread_handle; threads::ThreadTaskBase *thread_task; bool has_started; bool join_requested; void initialise(const long &stack_size); enum ThreadProperties { DefaultStackSize = -1 }; }; /***************************************************************************** ** Template Implementation [Thread] *****************************************************************************/ template Thread::Thread(void (C::*function)(), C &c, const Priority &priority, const long &stack_size) : thread_handle(NULL), thread_task(NULL), has_started(false), join_requested(false) { start(function, c, priority, stack_size); } template Thread::Thread(const F &function, const Priority &priority, const long &stack_size) : thread_handle(NULL), thread_task(NULL), has_started(false), join_requested(false) { start(function, priority, stack_size); } template Error Thread::start(void (C::*function)(), C &c, const Priority &priority, const long &stack_size) { // stack_size is ignored if ( has_started ) { ecl_debug_throw(StandardException(LOC,BusyError,"The thread has already been started.")); return Error(BusyError); // if in release mode, gracefully fall back to return values. } else { has_started = true; } thread_task = new threads::ThreadTask< BoundNullaryMemberFunction >(generateFunctionObject( function, c ), priority); DWORD threadid; thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threads::ThreadTask< BoundNullaryMemberFunction >::EntryPoint, thread_task, 0, &threadid); if (!thread_handle) { ecl_debug_throw(StandardException(LOC, UnknownError, "Failed to create thread.")); return Error(UnknownError); } BOOL bResult = FALSE; if (priority >= RealTimePriority1) { bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL); } switch (priority) { case CriticalPriority: bResult = SetThreadPriority(thread_handle, HIGH_PRIORITY_CLASS); break; case HighPriority: bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_ABOVE_NORMAL); break; case LowPriority: bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_BELOW_NORMAL); break; case BackgroundPriority: bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE); break; default: break; } if (!bResult) { ecl_debug_throw(threads::throwPriorityException(LOC)); } return Error(NoError); } template Error Thread::start(const F &function, const Priority &priority, const long &stack_size) { // stack_size is ignored if ( has_started ) { ecl_debug_throw(StandardException(LOC,BusyError,"The thread has already been started.")); return Error(BusyError); // if in release mode, gracefully fall back to return values. } else { has_started = true; } thread_task = new threads::ThreadTask::value >(function, priority); DWORD threadid; thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threads::ThreadTask::value >::EntryPoint, thread_task, 0, &threadid); if (!thread_handle) { ecl_debug_throw(StandardException(LOC, UnknownError, "Failed to create thread.")); return Error(UnknownError); } BOOL bResult = FALSE; if (priority >= RealTimePriority1) { bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL); } switch (priority) { case CriticalPriority: bResult = SetThreadPriority(thread_handle, HIGH_PRIORITY_CLASS); break; case HighPriority: bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_ABOVE_NORMAL); break; case LowPriority: bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_BELOW_NORMAL); break; case BackgroundPriority: bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE); break; default: break; } if (!bResult) { ecl_debug_throw(threads::throwPriorityException(LOC)); } return Error(NoError); } } // namespace ecl #endif /* ECL_IS_WIN32 */ #endif /* ECL_THREADS_THREAD_WIN_HPP_ */