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 завершается с ошибкой, процесс просто сработает прямо там. Чтобы сделать отказоустойчивую многопоточность, вам нужен пул или что-то подобное, что может быстро поймать такие вещи и, по крайней мере, исправить значимые сообщения об ошибках до того, как процесс завершится.