Files
tracy/public/client/TracyThread.hpp
Clément Grégoire f93d17a96f Add TRACY_PLATFORM_HEADER hook for unsupported platforms.
Extension point so private/unsupported platforms can plug in their own implementations of the kernel/libc primitives Tracy depends on, without patching the `#if`/`#elif` chains.

Projects supply a platform header via `-DTRACY_PLATFORM_HEADER="\"my_platform.h\""` at build time. Tracy includes it in any TU that needs the hooks. The header toggles per-category `TRACY_HAS_CUSTOM_*` macros and declares matching `tracy::Platform*` functions.

Available hooks:

- `TRACY_HAS_CUSTOM_THREAD_ID` → `PlatformGetThreadId`
- `TRACY_HAS_CUSTOM_USER_INFO` → `PlatformGetHostname`, `PlatformGetUserLogin`, `PlatformGetUserFullName`
- `TRACY_HAS_CUSTOM_SAFE_COPY` → `PlatformSafeMemcpy`
- `TRACY_HAS_CUSTOM_ALLOCATOR` → `PlatformMalloc`, `PlatformFree`, `PlatformRealloc`, `PlatformAllocatorInit`, `PlatformAllocatorThreadInit`, `PlatformAllocatorFinalize`, `PlatformAllocatorThreadFinalize`

Each hook is wired as the first arm of its respective `#if`/`#elif` chain, so existing supported platforms are unaffected.

Template files in `examples/CustomPlatform/` and a new subsection in `manual/tracy.tex` document the mechanism.
2026-05-24 15:42:42 +02:00

95 lines
1.7 KiB
C++

#ifndef __TRACYTHREAD_HPP__
#define __TRACYTHREAD_HPP__
#if defined _WIN32
# include <windows.h>
#else
# include <pthread.h>
#endif
#ifdef TRACY_MANUAL_LIFETIME
# include "../common/TracyAlloc.hpp"
#endif
namespace tracy
{
#ifdef TRACY_MANUAL_LIFETIME
extern thread_local bool RpThreadInitDone;
#endif
class ThreadExitHandler
{
public:
~ThreadExitHandler()
{
#ifdef TRACY_MANUAL_LIFETIME
# if defined TRACY_HAS_CUSTOM_ALLOCATOR
PlatformAllocatorThreadFinalize();
# elif defined TRACY_USE_RPMALLOC
rpmalloc_thread_finalize( 1 );
# endif
RpThreadInitDone = false;
#endif
}
};
#if defined _WIN32
class Thread
{
public:
Thread( void(*func)( void* ptr ), void* ptr )
: m_func( func )
, m_ptr( ptr )
, m_hnd( CreateThread( nullptr, 0, Launch, this, 0, nullptr ) )
{}
~Thread()
{
WaitForSingleObject( m_hnd, INFINITE );
CloseHandle( m_hnd );
}
HANDLE Handle() const { return m_hnd; }
private:
static DWORD WINAPI Launch( void* ptr ) { ((Thread*)ptr)->m_func( ((Thread*)ptr)->m_ptr ); return 0; }
void(*m_func)( void* ptr );
void* m_ptr;
HANDLE m_hnd;
};
#else
class Thread
{
public:
Thread( void(*func)( void* ptr ), void* ptr )
: m_func( func )
, m_ptr( ptr )
{
pthread_create( &m_thread, nullptr, Launch, this );
}
~Thread()
{
pthread_join( m_thread, nullptr );
}
pthread_t Handle() const { return m_thread; }
private:
static void* Launch( void* ptr ) { ((Thread*)ptr)->m_func( ((Thread*)ptr)->m_ptr ); return nullptr; }
void(*m_func)( void* ptr );
void* m_ptr;
pthread_t m_thread;
};
#endif
}
#endif