Std:: thread - назовем вашу нить

Новый С++ имеет этот тип std:: thread. Работает как шарм. Теперь я хотел бы дать каждому потоку имя для более легкой отладки (например, Java). С pthreads я бы сделал:

pthread_setname_np(pthread_self(), "thread_name");

но как я могу это сделать с помощью С++ 0x? Я знаю, что он использует pthreads под Linux, но я хотел бы сделать свое приложение переносимым. Возможно ли вообще?

Ответ 1

Портативный способ сделать это - сохранить карту имен, с помощью идентификатора потока, полученную из thread::get_id(). В качестве альтернативы, как указано в комментариях, вы можете использовать переменную thread_local, если вам нужно только получить доступ к имени из потока.

Если вам не нужна переносимость, вы можете получить базовый pthread_t от thread::native_handle() и делать с ним какие-то специфичные для платформы шантажи. Имейте в виду, что _np в функциях именования потоков означает "не posix", поэтому они не гарантируются для всех реализаций pthreads.

Ответ 2

Попытка сделать оболочку для работы со многими Linux, а также с Windows. При необходимости отредактируйте.

#ifdef _WIN32
#include <windows.h>
const DWORD MS_VC_EXCEPTION=0x406D1388;

#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
   DWORD dwType; // Must be 0x1000.
   LPCSTR szName; // Pointer to name (in user addr space).
   DWORD dwThreadID; // Thread ID (-1=caller thread).
   DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)


void SetThreadName(uint32_t dwThreadID, const char* threadName)
{

  // DWORD dwThreadID = ::GetThreadId( static_cast<HANDLE>( t.native_handle() ) );

   THREADNAME_INFO info;
   info.dwType = 0x1000;
   info.szName = threadName;
   info.dwThreadID = dwThreadID;
   info.dwFlags = 0;

   __try
   {
      RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
   }
   __except(EXCEPTION_EXECUTE_HANDLER)
   {
   }
}
void SetThreadName( const char* threadName)
{
    SetThreadName(GetCurrentThreadId(),threadName);
}

void SetThreadName( std::thread* thread, const char* threadName)
{
    DWORD threadId = ::GetThreadId( static_cast<HANDLE>( thread->native_handle() ) );
    SetThreadName(threadId,threadName);
}

#else
void SetThreadName(std::thread* thread, const char* threadName)
{
   auto handle = thread->native_handle();
   pthread_setname_np(handle,threadName);
}


#include <sys/prctl.h>
void SetThreadName( const char* threadName)
{
  prctl(PR_SET_NAME,threadName,0,0,0);
}

#endif

Ответ 3

Вы можете использовать std::thread::native_handle, чтобы получить заданный поток, лежащий в основе подкласса. Для этого нет стандартной функции.

Здесь вы можете найти пример .

Ответ 4

Для окон [отладчик] вы можете легко использовать "обычный" метод; http://msdn.microsoft.com/en-gb/library/xcb2z8hs.aspx

Просто нужен идентификатор потока, который вы можете получить через

#include <windows.h>
DWORD ThreadId = ::GetThreadId( static_cast<HANDLE>( mThread.native_handle() ) );

Ответ 5

Я видел это в системе, предшествующей С++ 11 (где мы в основном изобрели собственный класс Thread, который был очень похож на std:: thread) и в одном, который я написал довольно недавно.

В принципе, пул действительно ставит std:: thread 2 слоев вниз - у вас есть класс PoolThread, который содержит std:: thread плюс метаданные, такие как его имя, идентификатор и т.д. и структуру управления, которая связывает ее с ее контролем пул и сам ThreadPool. Вы хотите использовать пулы потоков в большинстве потоков кода по нескольким причинам:
1) Вы можете скрыть все явные "отделить", "присоединиться", начать поток от std:: thread construction и т.д. От пользователей. Это дает МНОГО более безопасный и чистый код.
2) Лучшее управление ресурсами. Слишком много потоков будет приводить к ухудшению производительности даже больше, чем слишком мало. Хорошо построенный пул может выполнять расширенные функции, такие как автоматическая балансировка нагрузки и очистка зависающих или заторможенных потоков.
3) Повторное использование потоков: std:: thread сам по себе проще всего использовать, выполняя каждую параллельную задачу в своем потоке. Но создание и разрушение потоков дороги, и вы можете легко увеличить скорость при параллельной обработке, если не будете осторожны. Таким образом, обычно имеет смысл иметь пул потоков, которые вытягивают рабочие задачи из очереди и только выходят после получения некоторого сигнала.
4) Обработка ошибок: std:: thread - это просто контекст выполнения. Если задача, которую вы выполняете на ней, выдает исключение без обработки или std:: thread ITSELF завершается с ошибкой, процесс просто сработает прямо там. Чтобы сделать отказоустойчивую многопоточность, вам нужен пул или что-то подобное, что может быстро поймать такие вещи и, по крайней мере, исправить значимые сообщения об ошибках до того, как процесс завершится.