2020-01-18 09:38:21 +01:00
/*
2020-01-24 16:45:29 +03:00
* Copyright ( c ) 2019 - 2020 , Sergey Bugaev < bugaevc @ serenityos . org >
2021-07-02 08:05:07 -04:00
* Copyright ( c ) 2021 , Spencer Dixon < spencercdixon @ gmail . com >
2020-01-18 09:38:21 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2019-08-25 18:55:56 +03:00
# pragma once
2022-11-12 14:13:40 +01:00
# include <AK/Assertions.h>
2023-08-06 01:31:42 -05:00
# include <AK/AtomicRefCounted.h>
2023-12-16 17:49:34 +03:30
# include <AK/ByteString.h>
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
# include <AK/DistinctNumeric.h>
2019-08-25 18:55:56 +03:00
# include <AK/Function.h>
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
# include <AK/Result.h>
2023-08-06 18:09:39 +02:00
# include <LibCore/EventReceiver.h>
2020-01-30 17:46:13 -06:00
# include <pthread.h>
2019-08-25 18:55:56 +03:00
2021-05-22 18:47:42 +02:00
namespace Threading {
2019-08-25 18:55:56 +03:00
2022-07-22 19:43:50 +01:00
AK_TYPEDEF_DISTINCT_ORDERED_ID ( intptr_t , ThreadError ) ;
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
2022-11-12 14:12:25 +01:00
// States of userspace threads are simplified over actual kernel states (and possibly POSIX states).
// There are only a couple of well-defined transitions between these states, and any attempt to call a function in a state where this is not allowed will crash the program.
enum class ThreadState : u8 {
// Thread has been constructed but not started.
// Transitions to Running via start().
Startable ,
// Thread has been started, might be running, and can be joined.
// Note that join() (valid to call in this state) only changes the thread state after the thread has exited, so it only ever transitions from Exited to Joined.
// Transitions to Detached via detach(), transitions to Exited when the thread finishes its action function.
Running ,
// Thread has not been detached and exited, and has to still be joined.
// Transitions to Joined via join().
Exited ,
// Thread has been started but also detached, meaning it cannot be joined.
// Transitions to DetachedExited when the thread finishes its action function.
Detached ,
// Thread has exited but was detached, meaning it cannot be joined.
DetachedExited ,
// Thread has exited and been joined.
Joined ,
} ;
2023-08-06 01:21:49 -05:00
class Thread final
2025-09-17 15:53:38 -05:00
: public AtomicRefCounted < Thread > {
2019-08-25 18:55:56 +03:00
public :
2024-05-17 17:14:06 -07:00
static NonnullRefPtr < Thread > construct ( ESCAPING Function < intptr_t ( ) > action , StringView thread_name = { } )
2023-08-06 01:21:49 -05:00
{
return adopt_ref ( * new Thread ( move ( action ) , thread_name ) ) ;
}
2024-05-17 17:14:06 -07:00
static ErrorOr < NonnullRefPtr < Thread > > try_create ( ESCAPING Function < intptr_t ( ) > action , StringView thread_name = { } )
2023-08-06 01:21:49 -05:00
{
return adopt_nonnull_ref_or_enomem ( new ( nothrow ) Thread ( move ( action ) , thread_name ) ) ;
}
2025-05-12 15:31:17 +02:00
~ Thread ( ) ;
2019-08-25 18:55:56 +03:00
2022-11-13 10:23:24 +01:00
ErrorOr < void > set_priority ( int priority ) ;
ErrorOr < int > get_priority ( ) const ;
2022-11-12 14:13:40 +01:00
// Only callable in the Startable state.
2019-08-25 18:55:56 +03:00
void start ( ) ;
2022-11-12 14:13:40 +01:00
// Only callable in the Running state.
2021-07-02 08:05:07 -04:00
void detach ( ) ;
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
2022-11-12 14:13:40 +01:00
// Only callable in the Running or Exited states.
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
template < typename T = void >
Result < T , ThreadError > join ( ) ;
2023-12-16 17:49:34 +03:30
ByteString thread_name ( ) const ;
2022-11-12 12:57:21 +01:00
pthread_t tid ( ) const ;
2022-11-12 14:13:40 +01:00
ThreadState state ( ) const ;
2022-11-12 12:57:21 +01:00
bool is_started ( ) const ;
2022-11-12 14:13:40 +01:00
bool needs_to_be_joined ( ) const ;
bool has_exited ( ) const ;
2019-08-25 18:55:56 +03:00
private :
2024-05-17 17:14:06 -07:00
explicit Thread ( ESCAPING Function < intptr_t ( ) > action , StringView thread_name = { } ) ;
2021-04-26 19:09:04 +02:00
Function < intptr_t ( ) > m_action ;
2024-11-28 13:04:39 +05:00
pthread_t m_tid { } ;
2023-12-16 17:49:34 +03:30
ByteString m_thread_name ;
2022-11-12 14:13:40 +01:00
Atomic < ThreadState > m_state { ThreadState : : Startable } ;
2019-08-25 18:55:56 +03:00
} ;
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
template < typename T >
Result < T , ThreadError > Thread : : join ( )
{
2022-11-12 14:13:40 +01:00
VERIFY ( needs_to_be_joined ( ) ) ;
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
void * thread_return = nullptr ;
int rc = pthread_join ( m_tid , & thread_return ) ;
if ( rc ! = 0 ) {
return ThreadError { rc } ;
}
2022-11-12 14:13:40 +01:00
// The other thread has now stopped running, so a TOCTOU bug is not possible.
// (If you call join from two different threads, you're doing something *very* wrong anyways.)
VERIFY ( m_state = = ThreadState : : Exited ) ;
m_state = ThreadState : : Joined ;
2021-04-10 18:29:06 +04:30
if constexpr ( IsVoid < T > )
LibThread: Improve semantics of Thread::join, and remove Thread::quit.
Thread::quit was created before the pthread_create_helper in pthread.cpp
that automagically calls pthread_exit from all pthreads after the user's
thread function exits. It is unused, and unecessary now.
Cleanup some logging, and make join return a Result<T, ThreadError>.
This also adds a new type, LibThread::ThreadError as an
AK::DistinctNumeric. Hopefully, this will make it possible to have a
Result<int, ThreadError> and have it compile? It also makes it clear
that the int there is an error at the call site.
By default, the T on join is void, meaning the caller doesn't care about
the return value from the thread.
As Result is a [[nodiscard]] type, also change the current caller of
join to explicitly ignore it.
Move the logging out of join as well, as it's the user's
responsibility whether to log or not.
2020-12-31 20:56:04 -07:00
return { } ;
else
return { static_cast < T > ( thread_return ) } ;
}
2019-08-25 18:55:56 +03:00
}
2022-11-12 13:58:18 +01:00
2024-11-28 13:04:39 +05:00
# ifdef AK_OS_WINDOWS
template < >
struct AK : : Formatter < pthread_t > : AK : : Formatter < FormatString > {
ErrorOr < void > format ( FormatBuilder & builder , pthread_t const & tid )
{
return Formatter < FormatString > : : format ( builder , " {} " sv , pthread_getw32threadid_np ( tid ) ) ;
}
} ;
# endif
2022-11-12 13:58:18 +01:00
template < >
struct AK : : Formatter < Threading : : Thread > : AK : : Formatter < FormatString > {
ErrorOr < void > format ( FormatBuilder & builder , Threading : : Thread const & thread )
{
return Formatter < FormatString > : : format ( builder , " Thread \" {} \" ({}) " sv , thread . thread_name ( ) , thread . tid ( ) ) ;
}
} ;
2022-11-12 14:12:25 +01:00
template < >
struct AK : : Formatter < Threading : : ThreadState > : AK : : Formatter < FormatString > {
ErrorOr < void > format ( FormatBuilder & builder , Threading : : ThreadState state )
{
2023-12-16 17:49:34 +03:30
ByteString name = " " ;
2022-11-12 14:12:25 +01:00
switch ( state ) {
case Threading : : ThreadState : : Detached :
name = " Detached " ;
break ;
case Threading : : ThreadState : : DetachedExited :
name = " DetachedExited " ;
break ;
case Threading : : ThreadState : : Exited :
name = " Exited " ;
break ;
case Threading : : ThreadState : : Joined :
name = " Joined " ;
break ;
case Threading : : ThreadState : : Running :
name = " Running " ;
break ;
case Threading : : ThreadState : : Startable :
name = " Startable " ;
break ;
default :
VERIFY_NOT_REACHED ( ) ;
}
return Formatter < FormatString > : : format ( builder , " {} " sv , name ) ;
}
} ;