Skip to content

Instantly share code, notes, and snippets.

@ppetraki
Last active April 19, 2019 17:31
Show Gist options
  • Save ppetraki/c09e3147efc07e192404a4452ca1905c to your computer and use it in GitHub Desktop.
Save ppetraki/c09e3147efc07e192404a4452ca1905c to your computer and use it in GitHub Desktop.
dump std::thread attributes. Uses neat local printf adapter.
#include <iostream>
#include <thread>
#include <mutex>
#include <cstdio>
#include <pthread.h>
#include <errno.h>
class fmt {
std::string buf_;
public:
#if 1
template <typename... Args>
fmt( std::string const& format, Args... args )
: buf_{
std::string( std::snprintf( nullptr, 0, format.c_str(), args... ) + 1 /* asciiz */, 0 )}
{
std::snprintf( const_cast<char*>(buf_.data()), buf_.size(), format.c_str(), args... );
}
#else
// just a more thorough explanation of the same constructor
template <typename... Args>
fmt( std::string const& format, Args... args )
{
// by not providing a buffer and sizeof(buffer), snprintf returns the
// total number of chars that would have been printed if size had been
// sufficiently large which is equal to the string and the size of
// it's formating, minus the ascii zero.
size_t size = std::snprintf( nullptr, 0, format.c_str(), args... );
size += 1; // asciiz
// now we know the entire size. it's assured in c++ versions >= c++11
// that std string's internal buffer is stored contiguously.
buf_ = std::string( size, 0 ); // fill constructor
// write the formatted string to our internal buffer
std::snprintf( const_cast<char*>(buf_.data()), buf_.size(), format.c_str(), args... );
}
#endif
friend std::ostream& operator<<( std::ostream& os, fmt const& op1 )
{
os << op1.buf_;
return os;
}
std::string str() const { return buf_; }
}; // class fmt
// adaption of,
// https://stackoverflow.com/questions/8408258/how-to-create-and-display-threads-attributes
// for std::thread
class thread_attr {
pthread_attr_t attr_;
std::thread::id tid_;
public:
thread_attr( std::thread& th )
{
tid_ = th.get_id();
pthread_attr_init( &attr_ );
if ( pthread_getattr_np( th.native_handle(), &attr_ ) ) {
// class destructor is not called if we throw an exception
// from within a constructor
pthread_attr_destroy( &attr_ );
throw std::runtime_error( "failed to get thread attributes" );
}
}
~thread_attr() noexcept { pthread_attr_destroy( &attr_ ); }
pthread_attr_t const& operator()() const { return attr_; }
std::size_t id() const { return std::hash<std::thread::id>{}( tid_ ); }
friend std::ostream& operator<<( std::ostream& os, thread_attr const& op1 )
{
const char* prefix = " ";
// set errno if we mess up
auto handle_error_en = []( int en, const char* msg ) {
errno = en;
throw std::runtime_error( msg );
};
os << "tid: " << op1.id() << std::endl;
const pthread_attr_t* attr = &op1();
int s, i;
s = pthread_attr_getdetachstate( attr, &i );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getdetachstate" );
os << fmt( "%sDetach state = %s\n", prefix,
( i == PTHREAD_CREATE_DETACHED )
? "PTHREAD_CREATE_DETACHED"
: ( i == PTHREAD_CREATE_JOINABLE ) ? "PTHREAD_CREATE_JOINABLE" : "???" );
s = pthread_attr_getscope( attr, &i );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getscope" );
os << fmt( "%sScope = %s\n", prefix,
( i == PTHREAD_SCOPE_SYSTEM )
? "PTHREAD_SCOPE_SYSTEM"
: ( i == PTHREAD_SCOPE_PROCESS ) ? "PTHREAD_SCOPE_PROCESS" : "???" );
s = pthread_attr_getinheritsched( attr, &i );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getinheritsched" );
os << fmt( "%sInherit scheduler = %s\n", prefix,
( i == PTHREAD_INHERIT_SCHED )
? "PTHREAD_INHERIT_SCHED"
: ( i == PTHREAD_EXPLICIT_SCHED ) ? "PTHREAD_EXPLICIT_SCHED" : "???" );
s = pthread_attr_getschedpolicy( attr, &i );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getschedpolicy" );
os << fmt( "%sScheduling policy = %s\n", prefix,
( i == SCHED_OTHER )
? "SCHED_OTHER"
: ( i == SCHED_FIFO ) ? "SCHED_FIFO"
: ( i == SCHED_RR ) ? "SCHED_RR" : "???" );
struct sched_param sp;
s = pthread_attr_getschedparam( attr, &sp );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getschedparam" );
os << fmt( "%sScheduling priority = %d\n", prefix, sp.sched_priority );
size_t v;
s = pthread_attr_getguardsize( attr, &v );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getguardsize" );
os << fmt( "%sGuard size = %d bytes\n", prefix, v );
void* stkaddr;
s = pthread_attr_getstack( attr, &stkaddr, &v );
if ( s != 0 ) handle_error_en( s, "pthread_attr_getstack" );
os << fmt( "%sStack address = %p\n", prefix, stkaddr );
os << fmt( "%sStack size = 0x%x bytes\n", prefix, v );
return os;
}
}; // class thread_attr
int main( int argc, char* argv[] )
{
(void)argc;
(void)argv;
std::mutex checkpoint;
std::thread th{[&]() { checkpoint.lock(); }};
auto attr = thread_attr( th );
checkpoint.unlock();
th.join();
std::cout << attr << std::endl;
return 0;
}
/* example output
tid: 23992903604122022
Detach state = PTHREAD_CREATE_JOINABLE
Scope = PTHREAD_SCOPE_SYSTEM
Inherit scheduler = PTHREAD_INHERIT_SCHED
Scheduling policy = SCHED_OTHER
Scheduling priority = 0
Guard size = 4096 bytes
Stack address = 0x7f8b9594c000
Stack size = 0x800000 bytes
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment