// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/utils/port/config.h" #ifdef TD_THREAD_PTHREAD #include "td/utils/common.h" #include "td/utils/Destructor.h" #include "td/utils/invoke.h" #include "td/utils/MovableValue.h" #include "td/utils/port/detail/ThreadIdGuard.h" #include "td/utils/port/thread_local.h" #include #include #include #include #include namespace td { namespace detail { class ThreadPthread { public: ThreadPthread() = default; ThreadPthread(const ThreadPthread &other) = delete; ThreadPthread &operator=(const ThreadPthread &other) = delete; ThreadPthread(ThreadPthread &&) = default; ThreadPthread &operator=(ThreadPthread &&other) { join(); is_inited_ = std::move(other.is_inited_); thread_ = other.thread_; return *this; } template explicit ThreadPthread(Function &&f, Args &&... args) { auto func = create_destructor([args = std::make_tuple(decay_copy(std::forward(f)), decay_copy(std::forward(args))...)]() mutable { invoke_tuple(std::move(args)); clear_thread_locals(); }); pthread_create(&thread_, nullptr, run_thread, func.release()); is_inited_ = true; } void join() { if (is_inited_.get()) { is_inited_ = false; pthread_join(thread_, nullptr); } } void detach() { if (is_inited_.get()) { is_inited_ = false; pthread_detach(thread_); } } ~ThreadPthread() { join(); } static unsigned hardware_concurrency() { return 8; } using id = pthread_t; private: MovableValue is_inited_; pthread_t thread_; template std::decay_t decay_copy(T &&v) { return std::forward(v); } static void *run_thread(void *ptr) { ThreadIdGuard thread_id_guard; auto func = unique_ptr(static_cast(ptr)); return nullptr; } }; namespace this_thread_pthread { inline void yield() { sched_yield(); } inline ThreadPthread::id get_id() { return pthread_self(); } } // namespace this_thread_pthread } // namespace detail } // namespace td #endif