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)
{
// Optimized lock + unlock
if (!m_mutex.is_free())
{
m_mutex.lock();
m_mutex.unlock();
}
m_mutex.lock_unlock();
(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)
{
std::lock_guard lock(m_mutex);

View File

@ -64,6 +64,11 @@ struct result_storage
{
return reinterpret_cast<const T*>(&data);
}
void destroy() noexcept
{
get()->~T();
}
};
template <>
@ -77,12 +82,12 @@ struct result_storage<void>
template <class Context, typename... 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>
struct thread_on_stop : std::bool_constant<false> {};
struct thread_abort : std::bool_constant<false> {};
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
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>
{
// 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.
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
void set_exception(std::exception_ptr ptr);
@ -277,6 +273,32 @@ class thread_ctrl final
friend class thread_base;
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
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);
}
public:
friend class thread_ctrl;
public:
// Normal forwarding constructor
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<Context, Args&&...>>>
named_thread(std::string_view name, Args&&... args)
@ -431,6 +454,10 @@ public:
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)
[[nodiscard]] decltype(auto) operator()()
{
@ -459,20 +486,38 @@ public:
return thread::m_state.load();
}
// Context type doesn't need virtual destructor
~named_thread()
// Try to set thread_state::aborting
named_thread& operator=(thread_state s)
{
if (s != thread_state::aborting)
{
ASSUME(0);
}
// Notify thread if not detached or terminated
if (thread::m_state.compare_and_swap_test(thread_state::created, thread_state::aborting))
{
// Additional notification if on_stop() method exists
if constexpr (thread_on_stop<Context>())
// Call on_abort() method if it's available
if constexpr (thread_abort<Context>())
{
Context::on_stop();
Context::on_abort();
}
thread::notify();
thread::join();
}
return *this;
}
// Context type doesn't need virtual destructor
~named_thread()
{
*this = thread_state::aborting;
thread::join();
if constexpr (!result::empty)
{
result::destroy();
}
}
};