2012-11-15 00:39:56 +01:00
# pragma once
2014-07-11 13:59:13 +02:00
static std : : thread : : id main_thread ;
2014-01-31 19:40:18 +01:00
class NamedThreadBase
2012-11-15 00:39:56 +01:00
{
2013-11-27 20:16:19 +01:00
std : : string m_name ;
2014-06-20 13:00:36 +02:00
std : : condition_variable m_signal_cv ;
std : : mutex m_signal_mtx ;
2013-06-30 10:46:29 +02:00
public :
2014-09-15 00:17:24 +02:00
std : : atomic < bool > m_tls_assigned ;
NamedThreadBase ( const std : : string & name ) : m_name ( name ) , m_tls_assigned ( false )
2014-01-31 19:40:18 +01:00
{
}
2012-11-15 00:39:56 +01:00
2014-09-15 00:17:24 +02:00
NamedThreadBase ( ) : m_tls_assigned ( false )
2014-01-31 19:40:18 +01:00
{
}
2013-06-30 10:46:29 +02:00
2013-11-27 20:16:19 +01:00
virtual std : : string GetThreadName ( ) const ;
virtual void SetThreadName ( const std : : string & name ) ;
2014-06-20 13:00:36 +02:00
2014-09-12 21:27:33 +02:00
void WaitForAnySignal ( u64 time = 1 ) ;
2014-06-20 13:00:36 +02:00
2014-08-25 20:09:48 +02:00
void Notify ( ) ;
2012-11-15 00:39:56 +01:00
} ;
2014-01-31 19:40:18 +01:00
NamedThreadBase * GetCurrentNamedThread ( ) ;
2014-08-20 16:23:48 +02:00
void SetCurrentNamedThread ( NamedThreadBase * value ) ;
2013-06-30 10:46:29 +02:00
2014-01-31 19:40:18 +01:00
class ThreadBase : public NamedThreadBase
2012-11-15 00:39:56 +01:00
{
2014-01-31 19:40:18 +01:00
protected :
std : : atomic < bool > m_destroy ;
std : : atomic < bool > m_alive ;
std : : thread * m_executor ;
2012-11-15 00:39:56 +01:00
2014-01-31 19:40:18 +01:00
mutable std : : mutex m_main_mutex ;
2013-06-30 10:46:29 +02:00
2014-01-31 19:40:18 +01:00
ThreadBase ( const std : : string & name ) ;
~ ThreadBase ( ) ;
2012-11-15 00:39:56 +01:00
2014-01-31 19:40:18 +01:00
public :
void Start ( ) ;
2014-02-14 20:50:02 +01:00
void Stop ( bool wait = true , bool send_destroy = true ) ;
2013-06-30 10:46:29 +02:00
2014-01-31 19:40:18 +01:00
bool Join ( ) const ;
bool IsAlive ( ) const ;
bool TestDestroy ( ) const ;
2012-11-15 00:39:56 +01:00
2014-01-31 19:40:18 +01:00
virtual void Task ( ) = 0 ;
2012-11-15 00:39:56 +01:00
} ;
2014-01-31 19:40:18 +01: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 18:27:52 +01:00
public :
2014-01-31 19:40:18 +01:00
void start ( std : : function < void ( ) > func ) ;
void detach ( ) ;
void join ( ) ;
bool joinable ( ) const ;
2014-10-10 23:33:57 +02:00
} ;
2014-10-17 22:13:25 +02:00
class s_mutex_t
{
} ;
class s_shared_mutex_t
{
} ;
class s_cond_var_t
{
//public:
// s_cond_var_t();
// ~s_cond_var_t();
//
// s_cond_var_t(s_cond_var_t& right) = delete;
// s_cond_var_t& operator = (s_cond_var_t& right) = delete;
//
// void wait();
// void wait_for();
//
// void notify();
// void notify_all();
} ;
class slw_mutex_t
{
} ;
class slw_recursive_mutex_t
{
} ;
class slw_shared_mutex_t
{
} ;
2014-10-16 18:29:41 +02:00
class waiter_map_t
2014-10-11 00:37:20 +02:00
{
2014-10-16 18:29:41 +02:00
// TODO: optimize (use custom lightweight readers-writer lock)
std : : mutex m_mutex ;
2014-10-11 00:37:20 +02:00
2014-10-16 18:29:41 +02:00
struct waiter_t
{
u64 signal_id ;
NamedThreadBase * thread ;
} ;
2014-10-11 00:37:20 +02:00
2014-10-16 18:29:41 +02:00
std : : vector < waiter_t > m_waiters ;
std : : string m_name ;
2014-10-10 23:33:57 +02:00
2014-10-16 18:29:41 +02:00
struct waiter_reg_t
{
2014-10-17 22:13:25 +02:00
NamedThreadBase * thread ;
2014-10-16 18:29:41 +02:00
const u64 signal_id ;
waiter_map_t & map ;
2014-10-17 22:13:25 +02:00
waiter_reg_t ( waiter_map_t & map , u64 signal_id )
: thread ( nullptr )
, signal_id ( signal_id )
, map ( map )
{
}
2014-10-16 18:29:41 +02:00
~ waiter_reg_t ( ) ;
2014-10-17 22:13:25 +02:00
void init ( ) ;
2014-10-16 18:29:41 +02:00
} ;
bool is_stopped ( u64 signal_id ) ;
2014-10-10 23:33:57 +02:00
2014-10-16 18:29:41 +02:00
public :
2014-10-17 22:13:25 +02:00
waiter_map_t ( const char * name )
: m_name ( name )
{
}
2014-10-16 18:29:41 +02:00
// wait until waiter_func() returns true, signal_id is an arbitrary number
2014-10-16 21:34:17 +02:00
template < typename WT > __forceinline void wait_op ( u64 signal_id , const WT waiter_func )
2014-10-10 23:33:57 +02:00
{
2014-10-16 18:29:41 +02:00
// register waiter
waiter_reg_t waiter ( * this , signal_id ) ;
2014-10-17 22:13:25 +02:00
// check condition or if emulator is stopped
while ( ! waiter_func ( ) & & ! is_stopped ( signal_id ) )
2014-10-16 18:29:41 +02:00
{
2014-10-17 22:13:25 +02:00
// initialize waiter (only first time)
waiter . init ( ) ;
2014-10-16 18:29:41 +02:00
// wait for 1 ms or until signal arrived
waiter . thread - > WaitForAnySignal ( 1 ) ;
}
2014-10-10 23:33:57 +02:00
}
2014-10-16 18:29:41 +02:00
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
void notify ( u64 signal_id ) ;
} ;