PLCnext API Documentation  20.0.0.24462
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  void SetStackSize(size_t value);
299 
302  size_t GetStackSize(void)const;
303 
311  void SetName(const String& value);
312 
315  const String& GetName(void)const;
316 
319  ThreadState GetState() const;
325  bool IsJoinable(void);
326 
327 public: // operations
330  void Start(void);
331 
335  void Join(void);
336 
342  void Interrupt(void);
343 
345  void Terminate(void);
346 
347 private: // typedefs/usings
348  using IThreadService = Arp::System::Ve::IThreadService;
349 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
350 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
351  using ThreadEventPtr = std::unique_ptr<ThreadEvent, ThreadEventDeleter>;
352 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
353 
354 private: // static methods
355  static void* RunInternal(void* pParam);
356  static void CheckInterruptOfCurrentThread(void);
357  static void SetStateOfCurrentThread(ThreadState state);
358  static String CreateDefaultThreadName(void);
359 
360 private: // methods
361  void CreateThreadInternal(void);
362  void CreateThreadInternal(const ThreadSettings& parameter);
363 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
364  void RunThread(ThreadBinaryCompatibilityExtensions* pBinCompat);
365 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
366  void RunThread(void);
367 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
368 
369 private: // deleted methods
370  Thread(const Thread& arg) = delete;
371  Thread& operator=(const Thread& arg) = delete;
372 
373 private: // fields
374  ThreadStartDelegate threadStart;
375  void* pStartParam;
376 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
377  ThreadBinaryCompatibilityExtensions* pBinaryCompatibilityExtensions;
378 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
379  IThreadService* pThreadService;
380 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
381  AutoResetEvent exitEvent;
382  std::atomic<ThreadState> state;
383  std::atomic<bool> interrupting;
384 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
385 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
386  ThreadEventPtr eventWakeupPtr;
387  Semaphore semIsStartable;
388  Semaphore semStart;
389  Semaphore semIsStarted;
390  std::atomic<bool> isActive;
391 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
392 
393 private: // static fields
394  static thread_local Thread* pCurrentThread;
395 };
396 
398 // inline methods of class Thread
399 template<class TInstance, class TFunction>
400 inline Thread::Thread(TInstance& instance, TFunction fn, void* pStartParam)
401  : Thread(&instance, fn, pStartParam)
402 {
403 }
404 
405 template<class TInstance, class TFunction>
406 inline Thread::Thread(const TInstance& instance, TFunction fn, void* pStartParam)
407  : Thread(&instance, fn, pStartParam)
408 {
409 }
410 
411 template<class TInstance, class TFunction>
412 inline Thread::Thread(TInstance* pInstance, TFunction fn, void* pStartParam)
413  : threadStart(make_delegate(pInstance, fn))
414  , pStartParam(pStartParam)
415 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
416  , pBinaryCompatibilityExtensions(nullptr)
417 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
418  , pThreadService(nullptr)
419 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
420  , state(ThreadState::Stopped)
421  , interrupting(false)
422 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
423 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
424  , eventWakeupPtr(nullptr)
425  , semIsStartable(0)
426  , semStart(0)
427  , semIsStarted(0)
428  , isActive(true)
429 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
430 {
431  this->CreateThreadInternal();
432 }
433 
434 template<class TInstance, class TFunction>
435 inline Thread::Thread(const TInstance* pInstance, TFunction fn, void* pStartParam)
436  : threadStart(make_delegate(pInstance, fn))
437  , pStartParam(pStartParam)
438 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
439  , pBinaryCompatibilityExtensions(nullptr)
440 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
441  , pThreadService(nullptr)
442 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
443  , state(ThreadState::Stopped)
444  , interrupting(false)
445 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
446 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
447  , eventWakeupPtr(nullptr)
448  , semIsStartable(0)
449  , semStart(0)
450  , semIsStarted(0)
451  , isActive(true)
452 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
453 {
454  this->CreateThreadInternal();
455 }
456 
457 inline Thread::Thread(ThreadStartDelegate&& threadStart, void* pStartParam)
458  : threadStart(std::move(threadStart))
459  , pStartParam(pStartParam)
460 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
461  , pBinaryCompatibilityExtensions(nullptr)
462 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
463  , pThreadService(nullptr)
464 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
465  , state(ThreadState::Stopped)
466  , interrupting(false)
467 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
468 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
469  , eventWakeupPtr(nullptr)
470  , semIsStartable(0)
471  , semStart(0)
472  , semIsStarted(0)
473  , isActive(true)
474 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
475 {
476  this->CreateThreadInternal();
477 }
478 
479 inline Thread::Thread(ThreadStartFunction threadStart, void* pStartParam)
480  : threadStart(make_delegate(threadStart))
481  , pStartParam(pStartParam)
482 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
483  , pBinaryCompatibilityExtensions(nullptr)
484 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
485  , pThreadService(nullptr)
486 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
487  , state(ThreadState::Stopped)
488  , interrupting(false)
489 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
490 #else // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
491  , eventWakeupPtr(nullptr)
492  , semIsStartable(0)
493  , semStart(0)
494  , semIsStarted(0)
495  , isActive(true)
496 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
497 {
498  this->CreateThreadInternal();
499 }
500 
501 template<class TInstance, class TFunction>
502 inline Thread::Thread(const ThreadSettings& settings, TInstance& instance, TFunction fn, void* pStartParam)
503  : Thread(settings, &instance, fn, pStartParam)
504 {
505 }
506 
507 template<class TInstance, class TFunction>
508 inline Thread::Thread(const ThreadSettings& settings, const TInstance& instance, TFunction fn, void* pStartParam)
509  : Thread(settings, &instance, fn, pStartParam)
510 {
511 }
512 
513 template<class TInstance, class TFunction>
514 inline Thread::Thread(const ThreadSettings& settings, TInstance* pInstance, TFunction fn, void* pStartParam)
515  : threadStart(make_delegate(pInstance, fn))
516  , pStartParam(pStartParam)
517 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
518  , pThreadService(nullptr)
519 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
520  , pBinaryCompatibilityExtensions(nullptr)
521 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
522  , state(ThreadState::Stopped)
523  , interrupting(false)
524 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
525  , eventWakeupPtr(nullptr)
526  , semIsCreatedPtr(nullptr)
527  , semStartPtr(nullptr)
528  , semIsStartedPtr(nullptr)
529 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
530 {
531  this->CreateThreadInternal(settings);
532 }
533 
534 template<class TInstance, class TFunction>
535 inline Thread::Thread(const ThreadSettings& settings, const TInstance* pInstance, TFunction fn, void* pStartParam)
536  : threadStart(make_delegate(pInstance, fn))
537  , pStartParam(pStartParam)
538 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
539  , pThreadService(nullptr)
540 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
541  , pBinaryCompatibilityExtensions(nullptr)
542 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
543  , state(ThreadState::Stopped)
544  , interrupting(false)
545 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
546  , eventWakeupPtr(nullptr)
547  , semIsCreatedPtr(nullptr)
548  , semStartPtr(nullptr)
549  , semIsStartedPtr(nullptr)
550 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
551 {
552  this->CreateThreadInternal(settings);
553 }
554 
555 inline Thread::Thread(ThreadSettings& settings, ThreadStartDelegate&& threadStart, void* pStartParam)
556  : Thread((const ThreadSettings&)settings, std::move(threadStart), pStartParam)
557 {
558 }
559 
560 inline Thread::Thread(ThreadSettings& settings, ThreadStartFunction threadStart, void* pStartParam)
561  : Thread((const ThreadSettings&)settings, threadStart, pStartParam)
562 {
563 }
564 
565 inline Thread::Thread(const ThreadSettings& settings, ThreadStartDelegate&& threadStart, void* pStartParam)
566  : threadStart(std::move(threadStart))
567  , pStartParam(pStartParam)
568 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
569  , pThreadService(nullptr)
570 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
571  , pBinaryCompatibilityExtensions(nullptr)
572 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
573  , state(ThreadState::Stopped)
574  , interrupting(false)
575 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
576  , eventWakeupPtr(nullptr)
577  , semIsCreatedPtr(nullptr)
578  , semStartPtr(nullptr)
579  , semIsStartedPtr(nullptr)
580 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
581 {
582  this->CreateThreadInternal(settings);
583 }
584 
585 inline Thread::Thread(const ThreadSettings& settings, ThreadStartFunction threadStart, void* pStartParam)
586  : threadStart(make_delegate(threadStart))
587  , pStartParam(pStartParam)
588 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
589  , pThreadService(nullptr)
590 #else // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
591  , pBinaryCompatibilityExtensions(nullptr)
592 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
593  , state(ThreadState::Stopped)
594  , interrupting(false)
595 #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
596  , eventWakeupPtr(nullptr)
597  , semIsCreatedPtr(nullptr)
598  , semStartPtr(nullptr)
599  , semIsStartedPtr(nullptr)
600 #endif // #ifdef THREAD_DONT_PROVIDE_BINARY_COMPATIBILITY
601 {
602  this->CreateThreadInternal(settings);
603 }
604 
605 inline bool Thread::IsRunning(void)const
606 {
607  return (this->GetState() == ThreadState::Running);
608 }
609 
611 {
612  return Thread::pCurrentThread;
613 }
614 
615 #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
616 inline void Thread::Interrupt(void)
617 {
618  this->interrupting = true;
619 }
620 #endif // #ifdef ARP_SYSTEM_COMMONS_THREADING_THREAD_BINARY_COMPAT_MODE
621 
622 inline ThreadState Thread::GetState(void) const
623 {
624  return this->state.load();
625 }
626 
627 }}}} // 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:610
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:605
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:616
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:400
ThreadState GetState() const
Returns the current state of the thread.
Definition: Thread.hpp:622