thread_win.hpp
Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 ** Ifdefs
00010 *****************************************************************************/
00011 
00012 #ifndef ECL_THREADS_THREAD_WIN_HPP_
00013 #define ECL_THREADS_THREAD_WIN_HPP_
00014 
00015 /*****************************************************************************
00016 ** Platform Check
00017 *****************************************************************************/
00018 
00019 #include <ecl/config/ecl.hpp>
00020 #if defined(ECL_IS_WIN32)
00021 
00022 /*****************************************************************************
00023 ** Includes
00024 *****************************************************************************/
00025 
00026 #include <windows.h>
00027 #include "thread_exceptions_pos.hpp"
00028 #include <ecl/config/macros.hpp>
00029 #include <ecl/concepts/nullary_function.hpp>
00030 #include <ecl/exceptions/standard_exception.hpp>
00031 #include <ecl/utilities/void.hpp>
00032 #include <ecl/utilities/function_objects.hpp>
00033 #include "priority_win.hpp"
00034 
00035 /*****************************************************************************
00036 ** Namespaces
00037 *****************************************************************************/
00038 
00039 namespace ecl {
00040 namespace threads {
00041 
00042 /*****************************************************************************
00043 ** Interface [ThreadTask]
00044 *****************************************************************************/
00051 class ECL_LOCAL ThreadTaskBase {
00052 public:
00053         virtual ~ThreadTaskBase() {};
00054 
00055 protected:
00056         ThreadTaskBase(const Priority& priority) : priority_level(priority) {}; 
00057         ecl::Priority priority_level;
00058 };
00068 template <typename F, bool IsReferenceWrapper = false>
00069 class ECL_LOCAL ThreadTask : public ThreadTaskBase {
00070 public:
00079         ThreadTask(const F &f, const Priority &priority) : ThreadTaskBase(priority), function(f) {
00080                 ecl_compile_time_concept_check(ecl::NullaryFunction<F>);
00081         };
00082         virtual ~ThreadTask() {}; 
00094         static unsigned int EntryPoint(void *ptr_this) {
00095             ThreadTask< F, false > *ptr = static_cast< ThreadTask< F, false > * >(ptr_this);
00096             (ptr->function)();
00097             return 0;
00098         }
00099 
00100 private:
00101         F function;
00102 };
00103 
00113 template <typename F>
00114 class ECL_LOCAL ThreadTask<F, true> : public ThreadTaskBase {
00115 public:
00124         ThreadTask(const F &f, const Priority &priority) : ThreadTaskBase(priority), function(f.reference()) {
00125                 ecl_compile_time_concept_check(ecl::NullaryFunction< typename F::type>);
00126         };
00127         virtual ~ThreadTask() {}; 
00138         static unsigned int EntryPoint(void *ptr_this) {
00139             ThreadTask< F, true > *ptr = static_cast< ThreadTask< F, true > * >(ptr_this);
00140             (ptr->function)();
00141             return 0;
00142         }
00143 
00144 private:
00145         typename F::type &function;
00146 };
00147 
00148 }; // namespace threads
00149 
00150 /*****************************************************************************
00151 ** Interface [Thread]
00152 *****************************************************************************/
00226 class ecl_threads_PUBLIC Thread {
00227 public:
00235         Thread() :
00236                 thread_handle(NULL),
00237                 thread_task(NULL),
00238                 has_started(false),
00239                 join_requested(false)
00240         {}
00260         Thread(VoidFunction function, const Priority &priority = DefaultPriority, const long &stack_size = -1 ) ecl_debug_throw_decl(StandardException);
00270         Error start(VoidFunction function, const Priority &priority = DefaultPriority, const long &stack_size = -1 ) ecl_debug_throw_decl(StandardException);
00294         template <typename C>
00295         Thread(void (C::*function)(), C &c, const Priority &priority = DefaultPriority,  const long &stack_size = -1 ) ecl_debug_throw_decl(StandardException);
00306         template <typename C>
00307         Error start(void (C::*function)(), C &c, const Priority &priority = DefaultPriority,  const long &stack_size = -1 ) ecl_debug_throw_decl(StandardException);
00308 
00347         template <typename F>
00348         Thread(const F &function, const Priority &priority = DefaultPriority,  const long &stack_size = -1 ) ecl_debug_throw_decl(StandardException);
00358         template <typename F>
00359         Error start(const F &function, const Priority &priority = DefaultPriority,  const long &stack_size = -1 ) ecl_debug_throw_decl(StandardException);
00360 
00369         virtual ~Thread();
00370 
00376         bool isRunning() { if ( thread_task == NULL ) { return false; } else { return true; } }
00377 
00391         void cancel() ecl_debug_throw_decl(StandardException);
00392 
00400         void join() ecl_assert_throw_decl(StandardException);
00401 
00402 
00403 private:
00404         HANDLE thread_handle;
00405     threads::ThreadTaskBase *thread_task;
00406     bool has_started;
00407     bool join_requested;
00408 
00409         void initialise(const long &stack_size) ecl_assert_throw_decl(StandardException);
00410 
00411         enum ThreadProperties {
00412                 DefaultStackSize = -1
00413         };
00414 };
00415 
00416 /*****************************************************************************
00417 ** Template Implementation [Thread]
00418 *****************************************************************************/
00419 
00420 template <typename C>
00421 Thread::Thread(void (C::*function)(), C &c, const Priority &priority, const long &stack_size) ecl_debug_throw_decl(StandardException) :
00422         thread_handle(NULL),
00423         thread_task(NULL),
00424         has_started(false),
00425         join_requested(false)
00426 {
00427         start<C>(function, c, priority, stack_size);
00428 
00429 }
00430 
00431 template <typename F>
00432 Thread::Thread(const F &function, const Priority &priority, const long &stack_size) ecl_debug_throw_decl(StandardException) :
00433         thread_handle(NULL),
00434         thread_task(NULL),
00435         has_started(false),
00436         join_requested(false)
00437 {
00438         start<F>(function, priority, stack_size);
00439 }
00440 
00441 template <typename C>
00442 Error Thread::start(void (C::*function)(), C &c, const Priority &priority, const long &stack_size) ecl_debug_throw_decl(StandardException)
00443 {
00444         // stack_size is ignored
00445 
00446         if ( has_started ) {
00447                 ecl_debug_throw(StandardException(LOC,BusyError,"The thread has already been started."));
00448                 return Error(BusyError); // if in release mode, gracefully fall back to return values.
00449         } else {
00450                 has_started = true;
00451         }
00452 
00453         thread_task = new threads::ThreadTask< BoundNullaryMemberFunction<C,void> >(generateFunctionObject( function, c ), priority);
00454 
00455     DWORD threadid;
00456 
00457     thread_handle = CreateThread(NULL,
00458         0,
00459         (LPTHREAD_START_ROUTINE)threads::ThreadTask< BoundNullaryMemberFunction<C,void> >::EntryPoint,
00460         thread_task,
00461         0,
00462         &threadid);
00463 
00464     if (!thread_handle) {
00465         ecl_debug_throw(StandardException(LOC, UnknownError, "Failed to create thread."));
00466         return Error(UnknownError);
00467     }
00468 
00469     BOOL bResult = FALSE;
00470 
00471     if (priority >= RealTimePriority1) {
00472         bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
00473     }
00474 
00475     switch (priority) {
00476         case CriticalPriority:
00477                 bResult = SetThreadPriority(thread_handle, HIGH_PRIORITY_CLASS);
00478             break;
00479         case HighPriority:
00480                 bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_ABOVE_NORMAL);
00481             break;
00482         case LowPriority:
00483                 bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_BELOW_NORMAL);
00484             break;
00485         case BackgroundPriority:
00486                 bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE);
00487             break;
00488         default:
00489             break;
00490     }
00491 
00492     if (!bResult) {
00493         ecl_debug_throw(threads::throwPriorityException(LOC));
00494     }
00495 
00496     return Error(NoError);
00497 }
00498 
00499 template <typename F>
00500 Error Thread::start(const F &function, const Priority &priority, const long &stack_size) ecl_debug_throw_decl(StandardException)
00501 {
00502         // stack_size is ignored
00503 
00504         if ( has_started ) {
00505                 ecl_debug_throw(StandardException(LOC,BusyError,"The thread has already been started."));
00506                 return Error(BusyError); // if in release mode, gracefully fall back to return values.
00507         } else {
00508                 has_started = true;
00509         }
00510 
00511         thread_task = new threads::ThreadTask<F, is_reference_wrapper<F>::value >(function, priority);
00512 
00513     DWORD threadid;
00514 
00515     thread_handle = CreateThread(NULL,
00516         0,
00517         (LPTHREAD_START_ROUTINE)threads::ThreadTask<F, is_reference_wrapper<F>::value >::EntryPoint,
00518         thread_task,
00519         0,
00520         &threadid);
00521 
00522     if (!thread_handle) {
00523         ecl_debug_throw(StandardException(LOC, UnknownError, "Failed to create thread."));
00524         return Error(UnknownError);
00525     }
00526 
00527     BOOL bResult = FALSE;
00528 
00529     if (priority >= RealTimePriority1) {
00530         bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
00531     }
00532 
00533     switch (priority) {
00534         case CriticalPriority:
00535                 bResult = SetThreadPriority(thread_handle, HIGH_PRIORITY_CLASS);
00536             break;
00537         case HighPriority:
00538                 bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_ABOVE_NORMAL);
00539             break;
00540         case LowPriority:
00541                 bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_BELOW_NORMAL);
00542             break;
00543         case BackgroundPriority:
00544                 bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE);
00545             break;
00546         default:
00547             break;
00548     }
00549 
00550     if (!bResult) {
00551         ecl_debug_throw(threads::throwPriorityException(LOC));
00552     }
00553 
00554     return Error(NoError);
00555 }
00556 
00557 }; // namespace ecl
00558 
00559 #endif /* ECL_IS_WIN32 */
00560 #endif /* ECL_THREADS_THREAD_WIN_HPP_ */


ecl_threads
Author(s): Daniel Stonier
autogenerated on Thu Jun 6 2019 21:18:01