153#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
171 [[
nodiscard]]
bool valid()
const override;
217 [[
nodiscard]]
bool joinable()
const override;
221 u_integer toHash()
const noexcept override;
223 std::string className()
const override;
230 void join()
override;
237 void detach()
override;
245#elif ORIGINAL_COMPILER_MSVC
250 [[
nodiscard]]
bool valid()
const override;
263 [[
nodiscard]]
bool joinable()
const override;
308 #if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
310 #elif ORIGINAL_COMPILER_MSVC
327 enum class joinPolicy {
332 [[
nodiscard]]
bool valid()
const override;
350 static constexpr auto AUTO_JOIN = joinPolicy::AUTO_JOIN;
353 static constexpr auto AUTO_DETACH = joinPolicy::AUTO_DETACH;
386#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
394#elif ORIGINAL_COMPILER_MSVC
435 [[
nodiscard]]
bool joinable()
const override;
472template <
typename DERIVED>
473template <
typename Callback>
480 throw sysError(
"Thread callback execution failed with message: " +
e.message());
485template <
typename DERIVED>
488 return this->valid();
491template <
typename DERIVED>
494 return !this->valid();
497template<
typename DERIVED>
502template<
typename DERIVED>
504 std::stringstream
ss;
505 ss <<
"(" << this->className() <<
" ";
506 ss <<
"#" << this->id();
512#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
513inline original::pThread::pThread() : handle(),
is_joinable() {}
515template<
typename Callback,
typename... ARGS>
516original::pThread::pThread(Callback c, ARGS&&... args) : handle(), is_joinable(true)
519 [func = std::forward<Callback>(c), ...lambda_args = std::forward<ARGS>(args)]()
mutable {
520 std::invoke(std::move(func), std::move(lambda_args)...);
523 using bound_callback =
decltype(bound_lambda);
524 using bound_thread_data = threadData<bound_callback>;
526 auto task =
new bound_thread_data(std::move(bound_lambda));
528 if (
const int code = pthread_create(&this->handle,
nullptr, &bound_thread_data::run, task); code != 0)
531 throw sysError(
"Failed to create thread (pthread_create returned " +
formatString(code) +
")");
535inline bool original::pThread::valid()
const
537 return this->handle != pthread_t{};
540inline original::pThread::pThread(pThread&& other) noexcept
542 this->operator=(std::move(other));
547 if (
this == &other) {
551 if (this->is_joinable && this->valid()) {
552 pthread_detach(this->handle);
555 this->handle = other.handle;
557 this->is_joinable = other.is_joinable;
558 other.is_joinable =
false;
564 std::memcpy(&
id, &this->handle,
sizeof(pthread_t));
568inline bool original::pThread::joinable()
const
570 return this->is_joinable;
574original::pThread::compareTo(
const pThread& other)
const {
575 if (this->
id() != other.id())
576 return this->id() > other.id() ? 1 : -1;
581original::pThread::toHash() const noexcept {
585inline std::string original::pThread::className()
const {
589inline void original::pThread::join() {
590 if (this->is_joinable){
591 if (
const int code = pthread_join(this->handle,
nullptr);
593 throw sysError(
"Failed to join thread (pthread_join returned " + formatString(code) +
")");
595 this->is_joinable =
false;
600inline void original::pThread::detach() {
601 if (this->is_joinable){
602 if (
const int code = pthread_detach(this->handle);
604 throw sysError(
"Failed to detach thread (pthread_detach returned " + formatString(code) +
")");
606 this->is_joinable =
false;
611inline original::pThread::~pThread()
613 if (this->is_joinable) {
617 std::cerr <<
"Fatal error in pThread destructor" << std::endl;
622#elif ORIGINAL_COMPILER_MSVC
623inline bool original::wThread::valid()
const
625 return this->handle != HANDLE{};
628inline original::wThread::wThread() : handle(), is_joinable() {}
630template <
typename Callback,
typename ... ARGS>
631original::wThread::wThread(Callback c, ARGS&&... args, ...) : handle(), is_joinable(true)
634 [func = std::forward<Callback>(c), ...lambda_args = std::forward<ARGS>(args)]()
mutable {
635 std::invoke(std::move(func), std::move(lambda_args)...);
638 using bound_callback =
decltype(bound_lambda);
639 using bound_thread_data = threadData<bound_callback>;
641 auto task =
new bound_thread_data(std::move(bound_lambda));
643 static auto threadEntry = [](LPVOID param) -> DWORD {
644 bound_thread_data::run(param);
648 this->handle = CreateThread(
nullptr, 0, threadEntry, task, 0,
nullptr);
649 if (this->handle ==
nullptr) {
651 throw sysError(
"Failed to create thread (CreateThread returned null)");
655inline original::wThread::wThread(wThread&& other) noexcept : wThread()
657 this->operator=(std::move(other));
662 if (
this == &other) {
666 if (this->is_joinable && this->valid()) {
667 CloseHandle(this->handle);
670 this->handle = other.handle;
672 this->is_joinable = other.is_joinable;
673 other.is_joinable =
false;
680 std::memcpy(&
id, &this->handle,
sizeof(HANDLE));
684inline bool original::wThread::joinable()
const
686 return this->is_joinable;
691 if (this->
id() != other.id())
692 return this->id() > other.id() ? 1 : -1;
701inline std::string original::wThread::className()
const
706inline void original::wThread::join()
708 WaitForSingleObject(this->handle, INFINITE);
709 this->is_joinable =
false;
713inline void original::wThread::detach()
715 CloseHandle(this->handle);
716 this->is_joinable =
false;
720inline original::wThread::~wThread()
722 if (this->is_joinable) {
726 std::cerr <<
"Fatal error in wThread destructor" << std::endl;
733inline bool original::thread::valid()
const
735 return this->thread_.operator bool();
739original::thread::thisId() {
741#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
742 auto handle = pthread_self();
743 std::memcpy(&
id, &handle,
sizeof(pthread_t));
744#elif ORIGINAL_COMPILER_MSVC
745 const auto handle = GetCurrentThreadId();
746 std::memcpy(&
id, &handle,
sizeof(HANDLE));
756#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
768 throw sysError(
"Failed to sleep thread (clock_nano-sleep returned " + formatString(
ret) +
771#elif ORIGINAL_COMPILER_MSVC
772 Sleep(
d.toDWMilliseconds());
787#if ORIGINAL_COMPILER_GCC || ORIGINAL_COMPILER_CLANG
790#elif ORIGINAL_COMPILER_MSVC
792 : thread_(
std::move(w_thread)), will_join(policy == AUTO_JOIN) {}
802 if (
this == &
other) {
806 this->thread_ = std::move(
other.thread_);
807 this->will_join =
other.will_join;
808 other.will_join =
false;
813original::thread::compareTo(
const thread&
other)
const {
819 return this->thread_.
toHash();
828 this->thread_.join();
833 this->thread_.detach();
839 this->will_join ? this->thread_.join() : this->thread_.detach();
841 std::cerr <<
"Fatal error in thread destructor: " <<
e.what() << std::endl;
847 return this->thread_.id();
852 return this->thread_.joinable();