2012-11-14 23:39:56 +00:00
# pragma once
2014-07-11 11:59:13 +00:00
static std : : thread : : id main_thread ;
2014-01-31 18:40:18 +00:00
class NamedThreadBase
2012-11-14 23:39:56 +00:00
{
2013-11-27 19:16:19 +00:00
std : : string m_name ;
2014-06-20 11:00:36 +00:00
std : : condition_variable m_signal_cv ;
std : : mutex m_signal_mtx ;
2013-06-30 08:46:29 +00:00
public :
2014-09-14 22:17:24 +00:00
std : : atomic < bool > m_tls_assigned ;
NamedThreadBase ( const std : : string & name ) : m_name ( name ) , m_tls_assigned ( false )
2014-01-31 18:40:18 +00:00
{
}
2012-11-14 23:39:56 +00:00
2014-09-14 22:17:24 +00:00
NamedThreadBase ( ) : m_tls_assigned ( false )
2014-01-31 18:40:18 +00:00
{
}
2013-06-30 08:46:29 +00:00
2013-11-27 19:16:19 +00:00
virtual std : : string GetThreadName ( ) const ;
virtual void SetThreadName ( const std : : string & name ) ;
2014-06-20 11:00:36 +00:00
2014-09-12 19:27:33 +00:00
void WaitForAnySignal ( u64 time = 1 ) ;
2014-06-20 11:00:36 +00:00
2014-08-25 18:09:48 +00:00
void Notify ( ) ;
2012-11-14 23:39:56 +00:00
} ;
2014-01-31 18:40:18 +00:00
NamedThreadBase * GetCurrentNamedThread ( ) ;
2014-08-20 14:23:48 +00:00
void SetCurrentNamedThread ( NamedThreadBase * value ) ;
2013-06-30 08:46:29 +00:00
2014-01-31 18:40:18 +00:00
class ThreadBase : public NamedThreadBase
2012-11-14 23:39:56 +00:00
{
2014-01-31 18:40:18 +00:00
protected :
std : : atomic < bool > m_destroy ;
std : : atomic < bool > m_alive ;
std : : thread * m_executor ;
2012-11-14 23:39:56 +00:00
2014-01-31 18:40:18 +00:00
mutable std : : mutex m_main_mutex ;
2013-06-30 08:46:29 +00:00
2014-01-31 18:40:18 +00:00
ThreadBase ( const std : : string & name ) ;
~ ThreadBase ( ) ;
2012-11-14 23:39:56 +00:00
2014-01-31 18:40:18 +00:00
public :
void Start ( ) ;
2014-02-14 19:50:02 +00:00
void Stop ( bool wait = true , bool send_destroy = true ) ;
2013-06-30 08:46:29 +00:00
2014-01-31 18:40:18 +00:00
bool Join ( ) const ;
bool IsAlive ( ) const ;
bool TestDestroy ( ) const ;
2012-11-14 23:39:56 +00:00
2014-01-31 18:40:18 +00:00
virtual void Task ( ) = 0 ;
2012-11-14 23:39:56 +00:00
} ;
2014-01-31 18:40:18 +00:00
class thread
{
std : : string m_name ;
std : : thread m_thr ;
public :
thread ( const std : : string & name , std : : function < void ( ) > func ) ;
thread ( const std : : string & name ) ;
thread ( ) ;
2014-02-19 17:27:52 +00:00
public :
2014-01-31 18:40:18 +00:00
void start ( std : : function < void ( ) > func ) ;
void detach ( ) ;
void join ( ) ;
bool joinable ( ) const ;
2014-10-10 21:33:57 +00:00
} ;
// for internal use (checks if Emu is stopped)
bool waiter_is_stopped ( const char * func_name , u64 signal_id ) ;
2014-10-10 22:37:20 +00:00
struct waiter_reg_t
{
const u64 signal_id ;
NamedThreadBase * const thread ;
waiter_reg_t ( u64 signal_id ) ;
~ waiter_reg_t ( ) ;
} ;
// wait until waiter_func() returns true, signal_id is an arbitrary number
2014-10-10 21:33:57 +00:00
template < typename WT > static __forceinline void waiter_op ( const char * func_name , u64 signal_id , const WT waiter_func )
{
2014-10-10 22:37:20 +00:00
// check condition
2014-10-10 21:33:57 +00:00
if ( waiter_func ( ) ) return ;
2014-10-10 22:37:20 +00:00
// register waiter
waiter_reg_t waiter ( signal_id ) ;
2014-10-10 21:33:57 +00:00
while ( true )
{
2014-10-10 22:37:20 +00:00
// wait for 1 ms or until signal arrived
waiter . thread - > WaitForAnySignal ( 1 ) ;
2014-10-10 21:33:57 +00:00
if ( waiter_is_stopped ( func_name , signal_id ) ) break ;
if ( waiter_func ( ) ) break ;
}
}
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
void waiter_signal ( u64 signal_id ) ;