Minor thread fixes

Call thread result destructor
This commit is contained in:
Nekotekina 2018-10-01 20:05:47 +03:00
parent 7a024f3355
commit 3359e9a51b
2 changed files with 66 additions and 33 deletions

View file

@ -1807,13 +1807,7 @@ bool thread_ctrl::_wait_for(u64 usec)
void thread_base::_notify(cond_variable thread_base::* ptr) void thread_base::_notify(cond_variable thread_base::* ptr)
{ {
// Optimized lock + unlock m_mutex.lock_unlock();
if (!m_mutex.is_free())
{
m_mutex.lock();
m_mutex.unlock();
}
(this->*ptr).notify_one(); (this->*ptr).notify_one();
} }
@ -1834,12 +1828,6 @@ thread_base::~thread_base()
} }
} }
std::exception_ptr thread_base::get_exception() const
{
std::lock_guard lock(m_mutex);
return m_exception;
}
void thread_base::set_exception(std::exception_ptr ptr) void thread_base::set_exception(std::exception_ptr ptr)
{ {
std::lock_guard lock(m_mutex); std::lock_guard lock(m_mutex);

View file

@ -64,6 +64,11 @@ struct result_storage
{ {
return reinterpret_cast<const T*>(&data); return reinterpret_cast<const T*>(&data);
} }
void destroy() noexcept
{
get()->~T();
}
}; };
template <> template <>
@ -77,12 +82,12 @@ struct result_storage<void>
template <class Context, typename... Args> template <class Context, typename... Args>
using result_storage_t = result_storage<std::invoke_result_t<Context, Args...>>; using result_storage_t = result_storage<std::invoke_result_t<Context, Args...>>;
// Detect on_stop() method (should return void) // Detect on_abort() method (should return void)
template <typename T, typename = void> template <typename T, typename = void>
struct thread_on_stop : std::bool_constant<false> {}; struct thread_abort : std::bool_constant<false> {};
template <typename T> template <typename T>
struct thread_on_stop<T, decltype(std::declval<named_thread<T>&>().on_stop())> : std::bool_constant<true> {}; struct thread_abort<T, decltype(std::declval<named_thread<T>&>().on_abort())> : std::bool_constant<true> {};
// Simple list of void() functors // Simple list of void() functors
class task_stack class task_stack
@ -153,7 +158,7 @@ public:
} }
}; };
// Thread base class // Thread base class (TODO: remove shared_ptr, make private base)
class thread_base : public std::enable_shared_from_this<thread_base> class thread_base : public std::enable_shared_from_this<thread_base>
{ {
// Native thread entry point function type // Native thread entry point function type
@ -240,15 +245,6 @@ public:
// Get CPU cycles since last time this function was called. First call returns 0. // Get CPU cycles since last time this function was called. First call returns 0.
u64 get_cycles(); u64 get_cycles();
// Get platform-specific thread handle
std::uintptr_t get_native_handle() const
{
return m_thread.load();
}
// Get exception
std::exception_ptr get_exception() const;
// Set exception // Set exception
void set_exception(std::exception_ptr ptr); void set_exception(std::exception_ptr ptr);
@ -277,6 +273,32 @@ class thread_ctrl final
friend class thread_base; friend class thread_base;
public: public:
// Get current thread name
static std::string_view get_name()
{
return g_tls_this_thread->m_name.get();
}
// Get thread name
template <typename T>
static std::string_view get_name(const named_thread<T>& thread)
{
return static_cast<const thread_base&>(thread).m_name.get();
}
// Set current thread name (not recommended)
static void set_name(std::string_view name)
{
g_tls_this_thread->m_name.assign(name);
}
// Set thread name (not recommended)
template <typename T>
static void set_name(named_thread<T>& thread, std::string_view name)
{
static_cast<thread_base&>(thread).m_name.assign(name);
}
// Read current state // Read current state
static inline thread_state state() static inline thread_state state()
{ {
@ -412,8 +434,9 @@ class named_thread final : public Context, result_storage_t<Context>, public thr
return thread::finalize(nullptr); return thread::finalize(nullptr);
} }
public: friend class thread_ctrl;
public:
// Normal forwarding constructor // Normal forwarding constructor
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>> template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>>
named_thread(std::string_view name, Args&&... args) named_thread(std::string_view name, Args&&... args)
@ -431,6 +454,10 @@ public:
thread::start(&named_thread::entry_point); thread::start(&named_thread::entry_point);
} }
named_thread(const named_thread&) = delete;
named_thread& operator=(const named_thread&) = delete;
// Wait for the completion and access result (if not void) // Wait for the completion and access result (if not void)
[[nodiscard]] decltype(auto) operator()() [[nodiscard]] decltype(auto) operator()()
{ {
@ -459,20 +486,38 @@ public:
return thread::m_state.load(); return thread::m_state.load();
} }
// Context type doesn't need virtual destructor // Try to set thread_state::aborting
~named_thread() named_thread& operator=(thread_state s)
{ {
if (s != thread_state::aborting)
{
ASSUME(0);
}
// Notify thread if not detached or terminated // Notify thread if not detached or terminated
if (thread::m_state.compare_and_swap_test(thread_state::created, thread_state::aborting)) if (thread::m_state.compare_and_swap_test(thread_state::created, thread_state::aborting))
{ {
// Additional notification if on_stop() method exists // Call on_abort() method if it's available
if constexpr (thread_on_stop<Context>()) if constexpr (thread_abort<Context>())
{ {
Context::on_stop(); Context::on_abort();
} }
thread::notify(); thread::notify();
}
return *this;
}
// Context type doesn't need virtual destructor
~named_thread()
{
*this = thread_state::aborting;
thread::join(); thread::join();
if constexpr (!result::empty)
{
result::destroy();
} }
} }
}; };