32 #pragma warning( disable : 4311 ) // trunc cast 33 #pragma warning( disable : 4302 ) // trunc cast 53 return GetCurrentThreadId();
56 const DWORD MS_VC_EXCEPTION = 0x406D1388;
58 #pragma pack( push, 8 ) 59 typedef struct tagTHREADNAME_INFO
68 void _SetThreadName(
DWORD dwThreadID,
const char*
name )
73 info.dwThreadID = dwThreadID;
78 RaiseException( MS_VC_EXCEPTION, 0,
sizeof( info ) /
sizeof( ULONG_PTR ), (ULONG_PTR*)&info );
80 __except ( EXCEPTION_EXECUTE_HANDLER )
84 void SetThreadName(
int threadid, std::string threadName )
88 _SetThreadName( threadid, threadName.c_str() );
97 res = pthread_attr_init( &create_detached_attr );
99 res = pthread_attr_setdetachstate( &create_detached_attr, PTHREAD_CREATE_DETACHED );
105 usleep( millis * 1000L );
109 return pthread_self();
120 catch ( std::exception& ex )
122 ERROR_PRINT <<
"Thread exception: " << ex.what() <<
"\n";
136 catch ( std::exception& ex )
138 ERROR_PRINT <<
"Thread exception: " << ex.what() <<
"\n";
150 void ( *entry )(
void* );
151 void ( *entry_noparam )( void );
163 void ( *entry )(
void* ) = td->
entry;
180 pthread_exit( NULL );
190 std::string threadName = td->
name;
192 unsigned threadid = 0;
193 HANDLE h = (HANDLE)_beginthreadex( NULL, 0,
thread_stub2, td, 0, &threadid );
197 "error in create_thread: {:d} {:d} \"{:s}\" \"{:s}\" {:d} {:d} {:s} {:d} {:d} {:d}\n" )
198 << errno << _doserrno << strerror( errno ) << strerror( _doserrno ) << threads++
208 SetThreadName( threadid, threadName );
217 int result = pthread_create( &thread, &create_detached_attr,
thread_stub2, td );
220 POLLOG.Format(
"error in create_thread: {:d} {:d} \"{:s}\" {:d} {:} {:s} {:} {:} {:d}\n" )
221 << result << errno << strerror( errno ) << threads++
223 <<
reinterpret_cast<const void*
>( td->
entry )
233 void start_thread(
void ( *entry )(
void* ),
const char* thread_name,
void* arg )
236 td->
name = thread_name;
249 td->
name = thread_name;
270 HANDLE ThreadMap::getThreadHandle(
size_t pid )
const 273 auto itr = _handles.find( pid );
274 if ( itr == _handles.end() )
284 _contents.insert( std::make_pair( pid, name ) );
287 if ( !DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hThread, 0,
288 FALSE, DUPLICATE_SAME_ACCESS ) )
290 ERROR_PRINT <<
"failed to duplicate thread handle\n";
293 _handles.insert( std::make_pair( pid, hThread ) );
301 auto itr = _handles.find( pid );
302 if ( itr != _handles.end() )
303 CloseHandle( itr->second );
304 _handles.erase( pid );
334 unsigned int max_count = std::thread::hardware_concurrency();
337 init( max_count, name );
343 init( max_count, name );
348 for (
unsigned int i = 0; i < max_count; ++i )
361 catch ( msg_queue::Canceled& )
364 catch ( std::exception& ex )
366 ERROR_PRINT <<
"Thread exception: " << ex.what() <<
"\n";
371 std::list<msg> remaining;
373 for (
auto& _f : remaining )
383 init( max_count, name );
413 auto promise = std::make_shared<std::promise<bool>>();
414 auto ret = promise->get_future();
419 promise->set_value(
true );
423 promise->set_exception( std::current_exception() );
451 BusyGuard(
bool* busy ) : _busy( busy ) { ( *_busy ) =
true; }
456 : _name( name ), _busy( false ), _thread(), _parent( parent )
486 catch ( msg_queue::Canceled& )
489 catch ( std::exception& ex )
491 ERROR_PRINT <<
"Thread exception: " << ex.what() <<
"\n";
518 for (
const auto& worker :
_threads )
520 if ( !worker->isbusy() )
526 size_t thread_num = _threads.size();
527 _threads.emplace_back(
new PoolWorker(
this,
_name +
" " + fmt::FormatInt( thread_num ).str() ) );
552 auto promise = std::make_shared<std::promise<bool>>();
553 auto ret = promise->get_future();
559 promise->set_value(
true );
563 promise->set_exception( std::current_exception() );
std::vector< std::unique_ptr< PoolWorker > > _threads
void init(unsigned int max_count, const std::string &name)
PoolWorker(DynTaskThreadPool *parent, const std::string &name)
DynTaskThreadPool * _parent
void pop_remaining(std::list< Message > *msgs)
void create_thread(ThreadData *td, bool dec_child=false)
typedef DWORD(WINAPI *__SymGetOptions)(VOID)
std::future< bool > checked_push(const msg &msg)
returns a future which will be set once the msg is processed
void start_thread(void(*entry)(void *), const char *thread_name, void *arg)
void force_backtrace(bool complete)
void init_pool(unsigned int max_count, const std::string &name)
std::function< void()> msg
void pop_wait(Message *msg)
void Unregister(size_t pid)
void CopyContents(Contents &out) const
std::future< bool > checked_push(const msg &msg)
returns a future which will be set once the msg is processed
void(* entry_noparam)(void)
void push(const msg &msg)
simply fire and forget only the deconstructor ensures the msg to be finished
static pthread_attr_t create_detached_attr
std::atomic< bool > _done
TaskThreadPool()
Creates a threadpool of workers. blocks on deconstruction eg: TaskThreadPool workers; for (...
ThreadRegister(const std::string &name)
void run_thread(void(*threadf)(void))
void push(Message const &msg)
std::atomic< unsigned int > child_threads
std::map< size_t, std::string > Contents
size_t threadpoolsize() const
static Clib::SpinLock pthread_attr_lock
void push(const msg &msg)
simply fire and forget only the deconstructor ensures the msg to be finished
void thread_sleep_ms(unsigned millis)
DynTaskThreadPool(const std::string &name)
Creates a dynamic threadpool of workers. if no idle worker is found creates a new worker thread block...
bool run(int argc, char **argv)
#define passert_always(exp)
void * thread_stub2(void *v_td)
std::lock_guard< SpinLock > SpinLockGuard
std::atomic< bool > _done
std::atomic< bool > exit_signalled
std::function< void()> msg
void Register(size_t pid, const std::string &name)
std::vector< std::thread > _threads