24 ThreadName

Setting the name of the thread in the code allows you to see the thread name in debugging tools such as Visual Studio. This is very convenient when there are lots of threads running in the process.

See:

ThreadName.h

// ThreadName.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd

#pragma once
#ifndef Ceda_cxThread_ThreadName_H
#define Ceda_cxThread_ThreadName_H

#include "cxThread.h"
#include "Ceda/cxUtils/xstring.h"

namespace ceda
{
cxThread_API void SetThreadName(const char* threadName);

inline void SetThreadName(const xstring& threadName)
{
    SetThreadName(threadName.c_str());    
}

} // namespace ceda

#endif

ThreadName.cpp

// ThreadName.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd

#include "ThreadName.h"
#ifdef _MSC_VER
    #include "Ceda/cxUtils/MsWindows.h"
#else
    #include <pthread.h>
#endif

namespace ceda
{
#if defined _WIN32 || defined __CYGWIN__
extern "C" typedef HRESULT (WINAPI *t_SetThreadDescription)( HANDLE, PCWSTR );
#endif

cxThread_API void SetThreadName(const char* name)
{
    #if defined _WIN32 || defined __CYGWIN__
        static auto SetThreadDescription = (t_SetThreadDescription) GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "SetThreadDescription" );
        if (SetThreadDescription)
        {
            wchar_t buf[256];
            mbstowcs( buf, name, 256 );
            SetThreadDescription( GetCurrentThread(), buf );
        }
        else
        {
            #if defined _MSC_VER
                #pragma pack(push,8)
                struct THREADNAME_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.
                };
                #pragma pack(pop)

                THREADNAME_INFO info{ 0x1000, name, (DWORD)-1, 0 };
                __try
                {
                    RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
                }
                __except(EXCEPTION_EXECUTE_HANDLER)
                {
                }
            #endif
        }
    #elif defined _GNU_SOURCE && !defined __EMSCRIPTEN__ && !defined __CYGWIN__
        char sizeLimitedName[16];
        strncpy(sizeLimitedName, name, 15);
        #ifdef __APPLE__
            pthread_setname_np(sizeLimitedName);
        #else
            pthread_setname_np(pthread_self(), sizeLimitedName);
        #endif
    #endif
}

} // namespace ceda