thread_win.hpp
Go to the documentation of this file.
1 
8 /*****************************************************************************
9 ** Ifdefs
10 *****************************************************************************/
11 
12 #ifndef ECL_THREADS_THREAD_WIN_HPP_
13 #define ECL_THREADS_THREAD_WIN_HPP_
14 
15 /*****************************************************************************
16 ** Platform Check
17 *****************************************************************************/
18 
19 #include <ecl/config/ecl.hpp>
20 #if defined(ECL_IS_WIN32)
21 
22 /*****************************************************************************
23 ** Includes
24 *****************************************************************************/
25 
26 #include <windows.h>
28 #include <ecl/config/macros.hpp>
31 #include <ecl/utilities/void.hpp>
33 #include "priority_win.hpp"
34 
35 /*****************************************************************************
36 ** Namespaces
37 *****************************************************************************/
38 
39 namespace ecl {
40 namespace threads {
41 
42 /*****************************************************************************
43 ** Interface [ThreadTask]
44 *****************************************************************************/
51 class ECL_LOCAL ThreadTaskBase {
52 public:
53  virtual ~ThreadTaskBase() {};
54 
55 protected:
56  ThreadTaskBase(const Priority& priority) : priority_level(priority) {};
57  ecl::Priority priority_level;
58 };
68 template <typename F, bool IsReferenceWrapper = false>
69 class ECL_LOCAL ThreadTask : public ThreadTaskBase {
70 public:
79  ThreadTask(const F &f, const Priority &priority) : ThreadTaskBase(priority), function(f) {
81  };
82  virtual ~ThreadTask() {};
94  static unsigned int EntryPoint(void *ptr_this) {
95  ThreadTask< F, false > *ptr = static_cast< ThreadTask< F, false > * >(ptr_this);
96  (ptr->function)();
97  return 0;
98  }
99 
100 private:
101  F function;
102 };
103 
113 template <typename F>
114 class ECL_LOCAL ThreadTask<F, true> : public ThreadTaskBase {
115 public:
124  ThreadTask(const F &f, const Priority &priority) : ThreadTaskBase(priority), function(f.reference()) {
126  };
127  virtual ~ThreadTask() {};
138  static unsigned int EntryPoint(void *ptr_this) {
139  ThreadTask< F, true > *ptr = static_cast< ThreadTask< F, true > * >(ptr_this);
140  (ptr->function)();
141  return 0;
142  }
143 
144 private:
145  typename F::type &function;
146 };
147 
148 }; // namespace threads
149 
150 /*****************************************************************************
151 ** Interface [Thread]
152 *****************************************************************************/
226 class ecl_threads_PUBLIC Thread {
227 public:
235  Thread() :
236  thread_handle(NULL),
237  thread_task(NULL),
238  has_started(false),
239  join_requested(false)
240  {}
260  Thread(VoidFunction function, const Priority &priority = DefaultPriority, const long &stack_size = -1 );
270  Error start(VoidFunction function, const Priority &priority = DefaultPriority, const long &stack_size = -1 );
294  template <typename C>
295  Thread(void (C::*function)(), C &c, const Priority &priority = DefaultPriority, const long &stack_size = -1 );
306  template <typename C>
307  Error start(void (C::*function)(), C &c, const Priority &priority = DefaultPriority, const long &stack_size = -1 );
308 
347  template <typename F>
348  Thread(const F &function, const Priority &priority = DefaultPriority, const long &stack_size = -1 );
358  template <typename F>
359  Error start(const F &function, const Priority &priority = DefaultPriority, const long &stack_size = -1 );
360 
369  virtual ~Thread();
370 
376  bool isRunning() { if ( thread_task == NULL ) { return false; } else { return true; } }
377 
391  void cancel();
392 
400  void join();
401 
402 
403 private:
404  HANDLE thread_handle;
405  threads::ThreadTaskBase *thread_task;
406  bool has_started;
407  bool join_requested;
408 
409  void initialise(const long &stack_size);
410 
411  enum ThreadProperties {
412  DefaultStackSize = -1
413  };
414 };
415 
416 /*****************************************************************************
417 ** Template Implementation [Thread]
418 *****************************************************************************/
419 
420 template <typename C>
421 Thread::Thread(void (C::*function)(), C &c, const Priority &priority, const long &stack_size) :
422  thread_handle(NULL),
423  thread_task(NULL),
424  has_started(false),
425  join_requested(false)
426 {
427  start<C>(function, c, priority, stack_size);
428 
429 }
430 
431 template <typename F>
432 Thread::Thread(const F &function, const Priority &priority, const long &stack_size) :
433  thread_handle(NULL),
434  thread_task(NULL),
435  has_started(false),
436  join_requested(false)
437 {
438  start<F>(function, priority, stack_size);
439 }
440 
441 template <typename C>
442 Error Thread::start(void (C::*function)(), C &c, const Priority &priority, const long &stack_size)
443 {
444  // stack_size is ignored
445 
446  if ( has_started ) {
447  ecl_debug_throw(StandardException(LOC,BusyError,"The thread has already been started."));
448  return Error(BusyError); // if in release mode, gracefully fall back to return values.
449  } else {
450  has_started = true;
451  }
452 
453  thread_task = new threads::ThreadTask< BoundNullaryMemberFunction<C,void> >(generateFunctionObject( function, c ), priority);
454 
455  DWORD threadid;
456 
457  thread_handle = CreateThread(NULL,
458  0,
459  (LPTHREAD_START_ROUTINE)threads::ThreadTask< BoundNullaryMemberFunction<C,void> >::EntryPoint,
460  thread_task,
461  0,
462  &threadid);
463 
464  if (!thread_handle) {
465  ecl_debug_throw(StandardException(LOC, UnknownError, "Failed to create thread."));
466  return Error(UnknownError);
467  }
468 
469  BOOL bResult = FALSE;
470 
471  if (priority >= RealTimePriority1) {
472  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
473  }
474 
475  switch (priority) {
476  case CriticalPriority:
477  bResult = SetThreadPriority(thread_handle, HIGH_PRIORITY_CLASS);
478  break;
479  case HighPriority:
480  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_ABOVE_NORMAL);
481  break;
482  case LowPriority:
483  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_BELOW_NORMAL);
484  break;
485  case BackgroundPriority:
486  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE);
487  break;
488  default:
489  break;
490  }
491 
492  if (!bResult) {
493  ecl_debug_throw(threads::throwPriorityException(LOC));
494  }
495 
496  return Error(NoError);
497 }
498 
499 template <typename F>
500 Error Thread::start(const F &function, const Priority &priority, const long &stack_size)
501 {
502  // stack_size is ignored
503 
504  if ( has_started ) {
505  ecl_debug_throw(StandardException(LOC,BusyError,"The thread has already been started."));
506  return Error(BusyError); // if in release mode, gracefully fall back to return values.
507  } else {
508  has_started = true;
509  }
510 
511  thread_task = new threads::ThreadTask<F, is_reference_wrapper<F>::value >(function, priority);
512 
513  DWORD threadid;
514 
515  thread_handle = CreateThread(NULL,
516  0,
517  (LPTHREAD_START_ROUTINE)threads::ThreadTask<F, is_reference_wrapper<F>::value >::EntryPoint,
518  thread_task,
519  0,
520  &threadid);
521 
522  if (!thread_handle) {
523  ecl_debug_throw(StandardException(LOC, UnknownError, "Failed to create thread."));
524  return Error(UnknownError);
525  }
526 
527  BOOL bResult = FALSE;
528 
529  if (priority >= RealTimePriority1) {
530  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
531  }
532 
533  switch (priority) {
534  case CriticalPriority:
535  bResult = SetThreadPriority(thread_handle, HIGH_PRIORITY_CLASS);
536  break;
537  case HighPriority:
538  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_ABOVE_NORMAL);
539  break;
540  case LowPriority:
541  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_BELOW_NORMAL);
542  break;
543  case BackgroundPriority:
544  bResult = SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE);
545  break;
546  default:
547  break;
548  }
549 
550  if (!bResult) {
551  ecl_debug_throw(threads::throwPriorityException(LOC));
552  }
553 
554  return Error(NoError);
555 }
556 
557 }; // namespace ecl
558 
559 #endif /* ECL_IS_WIN32 */
560 #endif /* ECL_THREADS_THREAD_WIN_HPP_ */
ecl_compile_time_concept_check
#define ecl_compile_time_concept_check(Model)
ECL_LOCAL
#define ECL_LOCAL
ecl::HighPriority
@ HighPriority
Definition: priority_common.hpp:48
ecl::LowPriority
@ LowPriority
Definition: priority_common.hpp:46
function_objects.hpp
ecl::VoidFunction
void(* VoidFunction)()
f
void f()
Definition: examples/mutex.cpp:27
ecl::NullaryFunction
ecl::DefaultPriority
@ DefaultPriority
Definition: priority_common.hpp:43
ecl::CriticalPriority
@ CriticalPriority
Definition: priority_common.hpp:49
void.hpp
standard_exception.hpp
priority_win.hpp
Priority scheduling for Windows.
ecl::RealTimePriority1
@ RealTimePriority1
Definition: priority_common.hpp:50
nullary_function.hpp
ecl::BackgroundPriority
@ BackgroundPriority
Definition: priority_common.hpp:45
macros.hpp
thread_exceptions_pos.hpp
Exception handlers for pthreads.
ecl
Embedded control libraries.
ecl::Priority
Priority
Shared abstraction of the scheduling priorities.
Definition: priority_common.hpp:36
generateFunctionObject
NullaryFreeFunction< R > generateFunctionObject(R(*function)())
ecl_debug_throw
#define ecl_debug_throw(exception)
ecl_threads_PUBLIC
#define ecl_threads_PUBLIC
Definition: macros.hpp:37


ecl_threads
Author(s): Daniel Stonier
autogenerated on Wed Mar 2 2022 00:16:43