PLCnext API Documentation  20.3.1.28622
Thread.hpp
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 #pragma once
7 #include "Arp/System/Core/Arp.h"
8 #include "Arp/System/Core/delegate.hxx"
9 #include "Arp/System/Commons/Threading/ThreadSettings.hpp"
10 #include "Arp/System/Commons/Logging.h"
11 #include "Arp/System/Commons/Threading/AutoResetEvent.hpp"
12 #include "Arp/System/Commons/Threading/ThreadState.hpp"
13 #include "Arp/System/Commons/Threading/Semaphore.hpp"
14 
15 #include <atomic>
16 
17 // forwards
18 namespace Arp { namespace System { namespace Ve
19 {
20 class IThreadService;
21 }}}
22 
23 #define ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
24 
25 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
26 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
27 namespace Arp { namespace System { namespace Commons { namespace Threading { namespace Internal
28 {
29 class ThreadEvent;
30 class ThreadEventDeleter
31 {
32 public:
33  void operator()(ThreadEvent*) const;
34 };
35 }}}}}
36 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
37 
38 namespace Arp { namespace System { namespace Commons { namespace Threading
39 {
40 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
41  // forwards
42  class ThreadBinaryCompatibilityExtensions;
43 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
44  using namespace Arp::System::Commons::Threading::Internal;
45 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
46 
91 class Thread : private Loggable<Thread>
92 {
93 private: // friends
94  friend class AutoResetEvent;
95 
96 public: // typedefs/usings
98  typedef void (*ThreadStartFunction)(void*);
99 
101  typedef delegate<void(void*)> ThreadStartDelegate;
102 
104  static const std::size_t CpuAffinityAll;
105 
106 public: // construction/destruction
107 
113  template<class TInstance, class TFunction>
114  Thread(TInstance& instance, TFunction fn, void* pStartParam = nullptr);
115 
121  template<class TInstance, class TFunction>
122  Thread(const TInstance& instance, TFunction fn, void* pStartParam = nullptr);
123 
129  template<class TInstance, class TFunction>
130  Thread(TInstance* pInstance, TFunction fn, void* pStartParam = nullptr);
131 
137  template<class TInstance, class TFunction>
138  Thread(const TInstance* pInstance, TFunction fn, void* pStartParam = nullptr);
139 
144  explicit Thread(ThreadStartDelegate&& threadStart, void* pStartParam = nullptr);
145 
154  Thread(ThreadStartFunction threadStart, void* pStartParam = nullptr);
155 
162  template<class TInstance, class TFunction>
163  Thread(const ThreadSettings& settings, TInstance& instance, TFunction fn, void* pStartParam = nullptr);
164 
171  template<class TInstance, class TFunction>
172  Thread(const ThreadSettings& settings, const TInstance& instance, TFunction fn, void* pStartParam = nullptr);
173 
180  template<class TInstance, class TFunction>
181  Thread(const ThreadSettings& settings, TInstance* pInstance, TFunction fn, void* pStartParam = nullptr);
182 
189  template<class TInstance, class TFunction>
190  Thread(const ThreadSettings& settings, const TInstance* pInstance, TFunction fn, void* pStartParam = nullptr);
191 
197  Thread(ThreadSettings& settings, ThreadStartDelegate&& threadStart, void* pStartParam = nullptr);
198 
204  Thread(ThreadSettings& settings, ThreadStartFunction threadStart, void* pStartParam = nullptr);
205 
211  Thread(const ThreadSettings& settings, ThreadStartDelegate&& threadStart, void* pStartParam = nullptr);
212 
218  Thread(const ThreadSettings& settings, ThreadStartFunction threadStart, void* pStartParam = nullptr);
219 
223  ~Thread(void);
224 
225 public: // static operations
226 
229  static void Sleep(size_t milliseconds);
230 
233  static size_t GetCurrentThreadId(void);
234 
237  static Thread* GetCurrentThread(void);
238 
247  static void SetAsynchronousCancelability(bool enable);
248 
249 public: // properties/setter/getter
251  bool IsRunning(void)const;
252 
270  void SetCpuAffinity(size_t mask);
271 
275  size_t GetCpuAffinity(void)const;
276 
280  void SetPriority(size_t value);
281 
284  size_t GetPriority(void)const;
285 
298  ARP_DEPRECATED("Set thread stack size at the constructor")
299  void SetStackSize(size_t value);
300 
303  size_t GetStackSize(void)const;
304 
312  void SetName(const String& value);
313 
316  const String& GetName(void)const;
317 
320  ThreadState GetState() const;
326  bool IsJoinable(void);
327 
328 public: // operations
331  void Start(void);
332 
336  void Join(void);
337 
343  void Interrupt(void);
344 
346  void Terminate(void);
347 
348 private: // typedefs/usings
349  using IThreadService = Arp::System::Ve::IThreadService;
350 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
351 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
352  using ThreadEventPtr = std::unique_ptr<ThreadEvent, ThreadEventDeleter>;
353 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
354 
355 private: // static methods
356  static void* RunInternal(void* pParam);
357  static void CheckInterruptOfCurrentThread(void);
358  static void SetStateOfCurrentThread(ThreadState state);
359  static String CreateDefaultThreadName(void);
360 
361 private: // methods
362  void CreateThreadInternal(void);
363  void CreateThreadInternal(const ThreadSettings& parameter);
364 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
365  void RunThread(ThreadBinaryCompatibilityExtensions* pBinCompat);
366 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
367  void RunThread(void);
368 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
369 
370 private: // deleted methods
371  Thread(const Thread& arg) = delete;
372  Thread& operator=(const Thread& arg) = delete;
373 
374 private: // fields
375  ThreadStartDelegate threadStart;
376  void* pStartParam;
377 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
378  ThreadBinaryCompatibilityExtensions* pBinaryCompatibilityExtensions;
379 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
380  IThreadService* pThreadService;
381 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
382  AutoResetEvent exitEvent;
383  std::atomic<ThreadState> state;
384  std::atomic<bool> interrupting;
385 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
386 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
387  ThreadEventPtr eventWakeupPtr;
388  Semaphore semIsStartable;
389  Semaphore semStart;
390  Semaphore semIsStarted;
391  std::atomic<bool> isActive;
392 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
393 
394 private: // static fields
395  static thread_local Thread* pCurrentThread;
396 };
397 
399 // inline methods of class Thread
400 template<class TInstance, class TFunction>
401 inline Thread::Thread(TInstance& instance, TFunction fn, void* pStartParam)
402  : Thread(&instance, fn, pStartParam)
403 {
404 }
405 
406 template<class TInstance, class TFunction>
407 inline Thread::Thread(const TInstance& instance, TFunction fn, void* pStartParam)
408  : Thread(&instance, fn, pStartParam)
409 {
410 }
411 
412 template<class TInstance, class TFunction>
413 inline Thread::Thread(TInstance* pInstance, TFunction fn, void* pStartParam)
414  : threadStart(make_delegate(pInstance, fn))
415  , pStartParam(pStartParam)
416 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
417  , pBinaryCompatibilityExtensions(nullptr)
418 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
419  , pThreadService(nullptr)
420 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
421  , state(ThreadState::Stopped)
422  , interrupting(false)
423 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
424 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
425  , eventWakeupPtr(nullptr)
426  , semIsStartable(0)
427  , semStart(0)
428  , semIsStarted(0)
429  , isActive(true)
430 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
431 {
432  this->CreateThreadInternal();
433 }
434 
435 template<class TInstance, class TFunction>
436 inline Thread::Thread(const TInstance* pInstance, TFunction fn, void* pStartParam)
437  : threadStart(make_delegate(pInstance, fn))
438  , pStartParam(pStartParam)
439 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
440  , pBinaryCompatibilityExtensions(nullptr)
441 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
442  , pThreadService(nullptr)
443 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
444  , state(ThreadState::Stopped)
445  , interrupting(false)
446 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
447 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
448  , eventWakeupPtr(nullptr)
449  , semIsStartable(0)
450  , semStart(0)
451  , semIsStarted(0)
452  , isActive(true)
453 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
454 {
455  this->CreateThreadInternal();
456 }
457 
458 inline Thread::Thread(ThreadStartDelegate&& threadStart, void* pStartParam)
459  : threadStart(std::move(threadStart))
460  , pStartParam(pStartParam)
461 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
462  , pBinaryCompatibilityExtensions(nullptr)
463 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
464  , pThreadService(nullptr)
465 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
466  , state(ThreadState::Stopped)
467  , interrupting(false)
468 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
469 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
470  , eventWakeupPtr(nullptr)
471  , semIsStartable(0)
472  , semStart(0)
473  , semIsStarted(0)
474  , isActive(true)
475 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
476 {
477  this->CreateThreadInternal();
478 }
479 
480 inline Thread::Thread(ThreadStartFunction threadStart, void* pStartParam)
481  : threadStart(make_delegate(threadStart))
482  , pStartParam(pStartParam)
483 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
484  , pBinaryCompatibilityExtensions(nullptr)
485 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
486  , pThreadService(nullptr)
487 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
488  , state(ThreadState::Stopped)
489  , interrupting(false)
490 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
491 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
492  , eventWakeupPtr(nullptr)
493  , semIsStartable(0)
494  , semStart(0)
495  , semIsStarted(0)
496  , isActive(true)
497 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
498 {
499  this->CreateThreadInternal();
500 }
501 
502 template<class TInstance, class TFunction>
503 inline Thread::Thread(const ThreadSettings& settings, TInstance& instance, TFunction fn, void* pStartParam)
504  : Thread(settings, &instance, fn, pStartParam)
505 {
506 }
507 
508 template<class TInstance, class TFunction>
509 inline Thread::Thread(const ThreadSettings& settings, const TInstance& instance, TFunction fn, void* pStartParam)
510  : Thread(settings, &instance, fn, pStartParam)
511 {
512 }
513 
514 template<class TInstance, class TFunction>
515 inline Thread::Thread(const ThreadSettings& settings, TInstance* pInstance, TFunction fn, void* pStartParam)
516  : threadStart(make_delegate(pInstance, fn))
517  , pStartParam(pStartParam)
518 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
519  , pThreadService(nullptr)
520 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
521  , pBinaryCompatibilityExtensions(nullptr)
522 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
523  , state(ThreadState::Stopped)
524  , interrupting(false)
525 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
526  , eventWakeupPtr(nullptr)
527  , semIsCreatedPtr(nullptr)
528  , semStartPtr(nullptr)
529  , semIsStartedPtr(nullptr)
530 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
531 {
532  this->CreateThreadInternal(settings);
533 }
534 
535 template<class TInstance, class TFunction>
536 inline Thread::Thread(const ThreadSettings& settings, const TInstance* pInstance, TFunction fn, void* pStartParam)
537  : threadStart(make_delegate(pInstance, fn))
538  , pStartParam(pStartParam)
539 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
540  , pThreadService(nullptr)
541 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
542  , pBinaryCompatibilityExtensions(nullptr)
543 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
544  , state(ThreadState::Stopped)
545  , interrupting(false)
546 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
547  , eventWakeupPtr(nullptr)
548  , semIsCreatedPtr(nullptr)
549  , semStartPtr(nullptr)
550  , semIsStartedPtr(nullptr)
551 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
552 {
553  this->CreateThreadInternal(settings);
554 }
555 
556 inline Thread::Thread(ThreadSettings& settings, ThreadStartDelegate&& threadStart, void* pStartParam)
557  : Thread((const ThreadSettings&)settings, std::move(threadStart), pStartParam)
558 {
559 }
560 
561 inline Thread::Thread(ThreadSettings& settings, ThreadStartFunction threadStart, void* pStartParam)
562  : Thread((const ThreadSettings&)settings, threadStart, pStartParam)
563 {
564 }
565 
566 inline Thread::Thread(const ThreadSettings& settings, ThreadStartDelegate&& threadStart, void* pStartParam)
567  : threadStart(std::move(threadStart))
568  , pStartParam(pStartParam)
569 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
570  , pThreadService(nullptr)
571 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
572  , pBinaryCompatibilityExtensions(nullptr)
573 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
574  , state(ThreadState::Stopped)
575  , interrupting(false)
576 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
577  , eventWakeupPtr(nullptr)
578  , semIsCreatedPtr(nullptr)
579  , semStartPtr(nullptr)
580  , semIsStartedPtr(nullptr)
581 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
582 {
583  this->CreateThreadInternal(settings);
584 }
585 
586 inline Thread::Thread(const ThreadSettings& settings, ThreadStartFunction threadStart, void* pStartParam)
587  : threadStart(make_delegate(threadStart))
588  , pStartParam(pStartParam)
589 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
590  , pThreadService(nullptr)
591 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
592  , pBinaryCompatibilityExtensions(nullptr)
593 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
594  , state(ThreadState::Stopped)
595  , interrupting(false)
596 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
597  , eventWakeupPtr(nullptr)
598  , semIsCreatedPtr(nullptr)
599  , semStartPtr(nullptr)
600  , semIsStartedPtr(nullptr)
601 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
602 {
603  this->CreateThreadInternal(settings);
604 }
605 
606 inline bool Thread::IsRunning(void)const
607 {
608  return (this->GetState() == ThreadState::Running);
609 }
610 
612 {
613  return Thread::pCurrentThread;
614 }
615 
616 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
617 inline void Thread::Interrupt(void)
618 {
619  this->interrupting = true;
620 }
621 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
622 
623 inline ThreadState Thread::GetState(void) const
624 {
625  return this->state.load();
626 }
627 
628 }}}} // end of namespace Arp::System::Commons::Threading
Event object to signal a single thread that an event has occurred. Can be used to synchronize threads...
Definition: AutoResetEvent.hpp:22
delegate< R(A...)> make_delegate(R(*const function_ptr)(A...)) noexcept
Creates a delegate from a static function.
Definition: delegate.hxx:215
static Thread * GetCurrentThread(void)
Returns the current thread of the calling context.
Definition: Thread.hpp:611
Namespace of the C++ standard library
static const std::size_t CpuAffinityAll
Use this constant to express an affinity of the thread to all available CPUs aka. cores...
Definition: Thread.hpp:104
The Thread-class provides methods to execute functions and methods in a separate thread.
Definition: Thread.hpp:91
delegate< void(void *)> ThreadStartDelegate
Definition of signature of class method to be executed in a separate thread.
Definition: Thread.hpp:101
Implementation of named or unnamed semaphore used to synchronize processes and threads.
Definition: Semaphore.hpp:22
summary>Thread is either waiting for an event, currently sleeping or waits for another thread to fini...
bool IsRunning(void) const
Determines if this thread is in running state.
Definition: Thread.hpp:606
Container class for adaptable thread settings.
Definition: ThreadSettings.hpp:12
Root namespace for the PLCnext API
ThreadState
Possible thread states.
Definition: ThreadState.hpp:14
void Interrupt(void)
Interrupts the currents execution.
Definition: Thread.hpp:617
void(* ThreadStartFunction)(void *)
Definition of signature of function to be executed in a separate thread.
Definition: Thread.hpp:98
System components used by the System, Device, Plc or Io domains.
Thread(TInstance &instance, TFunction fn, void *pStartParam=nullptr)
Constructs a Thread instance for a class method.
Definition: Thread.hpp:401
ThreadState GetState() const
Returns the current state of the thread.
Definition: Thread.hpp:623