mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 08:41:02 +08:00
#53 [Core] Fixed problem with removing ThreadStorage for alive threads. But Linux would have another problem: potential memory leak or potential crash at your choise :)) because these wonderful pthreads does not allow to check thread state :(
This commit is contained in:
parent
86f2ff0c71
commit
c813ea655d
@ -2,20 +2,35 @@ message(STATUS "")
|
|||||||
message(STATUS "EASY_PROFILER.Core version = ${EASY_PRODUCT_VERSION_STRING}")
|
message(STATUS "EASY_PROFILER.Core version = ${EASY_PRODUCT_VERSION_STRING}")
|
||||||
message(STATUS "")
|
message(STATUS "")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###########################################################
|
||||||
|
# EasyProfiler options:
|
||||||
|
set(EASY_OPTION_IMPLICIT_THREAD_REGISTER_TEXT "Enable new threads registration when collecting context switch events")
|
||||||
set(EASY_DEFAULT_PORT 28077 CACHE STRING "Default listening port")
|
set(EASY_DEFAULT_PORT 28077 CACHE STRING "Default listening port")
|
||||||
set(EASY_OPTION_LISTEN OFF CACHE BOOL "Enable automatic startListen on startup")
|
set(EASY_OPTION_LISTEN OFF CACHE BOOL "Enable automatic startListen on startup")
|
||||||
set(EASY_OPTION_PROFILE_SELF OFF CACHE BOOL "Enable self profiling (measure time for internal storage expand)")
|
set(EASY_OPTION_PROFILE_SELF OFF CACHE BOOL "Enable self profiling (measure time for internal storage expand)")
|
||||||
set(EASY_OPTION_PROFILE_SELF_BLOCKS_ON OFF CACHE BOOL "Storage expand default status (profiler::ON or profiler::OFF)")
|
set(EASY_OPTION_PROFILE_SELF_BLOCKS_ON OFF CACHE BOOL "Storage expand default status (profiler::ON or profiler::OFF)")
|
||||||
set(EASY_OPTION_LOG OFF CACHE BOOL "Print errors to stderr")
|
set(EASY_OPTION_LOG OFF CACHE BOOL "Print errors to stderr")
|
||||||
set(EASY_OPTION_PREDEFINED_COLORS ON CACHE BOOL "Use predefined set of colors (see profiler_colors.h). If you want to use your own colors palette you can turn this option OFF")
|
set(EASY_OPTION_PREDEFINED_COLORS ON CACHE BOOL "Use predefined set of colors (see profiler_colors.h). If you want to use your own colors palette you can turn this option OFF")
|
||||||
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build easy_profiler as shared library.")
|
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build easy_profiler as shared library.")
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(EASY_OPTION_EVENT_TRACING ON CACHE BOOL "Enable event tracing by default")
|
set(EASY_OPTION_IMPLICIT_THREAD_REGISTRATION ON CACHE BOOL ${EASY_OPTION_IMPLICIT_THREAD_REGISTER_TEXT})
|
||||||
set(EASY_OPTION_LOW_PRIORITY_EVENT_TRACING ON CACHE BOOL "Set low priority for event tracing thread")
|
set(EASY_OPTION_EVENT_TRACING ON CACHE BOOL "Enable event tracing by default")
|
||||||
endif (WIN32)
|
set(EASY_OPTION_LOW_PRIORITY_EVENT_TRACING ON CACHE BOOL "Set low priority for event tracing thread")
|
||||||
set(BUILD_WITH_CHRONO_STEADY_CLOCK OFF CACHE BOOL "Use std::chrono::steady_clock as a timer" )
|
else ()
|
||||||
|
set(EASY_OPTION_IMPLICIT_THREAD_REGISTRATION OFF CACHE BOOL ${EASY_OPTION_IMPLICIT_THREAD_REGISTER_TEXT})
|
||||||
|
set(EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS OFF CACHE BOOL "Enable easy_profiler to remove empty unguarded threads. This fixes potential memory leak on Unix systems, but may lead to an application crash! This is used if your compiler does not support C++11 thread_local feature or EASY_OPTION_IMPLICIT_THREAD_REGISTER is ON")
|
||||||
|
endif ()
|
||||||
|
set(BUILD_WITH_CHRONO_STEADY_CLOCK OFF CACHE BOOL "Use std::chrono::steady_clock as a timer" )
|
||||||
set(BUILD_WITH_CHRONO_HIGH_RESOLUTION_CLOCK OFF CACHE BOOL "Use std::chrono::high_resolution_clock as a timer")
|
set(BUILD_WITH_CHRONO_HIGH_RESOLUTION_CLOCK OFF CACHE BOOL "Use std::chrono::high_resolution_clock as a timer")
|
||||||
|
# End EasyProfiler options.
|
||||||
|
###########################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Print EasyProfiler options status:
|
||||||
message(STATUS "-------- EASY_PROFILER OPTIONS: --------")
|
message(STATUS "-------- EASY_PROFILER OPTIONS: --------")
|
||||||
if (BUILD_WITH_CHRONO_STEADY_CLOCK)
|
if (BUILD_WITH_CHRONO_STEADY_CLOCK)
|
||||||
message(STATUS " Use std::chrono::steady_clock as a timer")
|
message(STATUS " Use std::chrono::steady_clock as a timer")
|
||||||
@ -33,20 +48,39 @@ message(STATUS " Default listening port = ${EASY_DEFAULT_PORT}")
|
|||||||
message(STATUS " Auto-start listening = ${EASY_OPTION_LISTEN}")
|
message(STATUS " Auto-start listening = ${EASY_OPTION_LISTEN}")
|
||||||
message(STATUS " Profile self = ${EASY_OPTION_PROFILE_SELF}")
|
message(STATUS " Profile self = ${EASY_OPTION_PROFILE_SELF}")
|
||||||
message(STATUS " Profile self blocks initial status = ${EASY_OPTION_PROFILE_SELF_BLOCKS_ON}")
|
message(STATUS " Profile self blocks initial status = ${EASY_OPTION_PROFILE_SELF_BLOCKS_ON}")
|
||||||
|
message(STATUS " Implicit thread registration = ${EASY_OPTION_IMPLICIT_THREAD_REGISTRATION}")
|
||||||
|
if (EASY_OPTION_IMPLICIT_THREAD_REGISTRATION)
|
||||||
|
message(STATUS " WARNING! Implicit thread registration for Unix systems can lead to memory leak")
|
||||||
|
message(STATUS " because there is no possibility to check if thread is alive and remove dead threads.")
|
||||||
|
endif ()
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
message(STATUS " Event tracing = ${EASY_OPTION_EVENT_TRACING}")
|
message(STATUS " Event tracing = ${EASY_OPTION_EVENT_TRACING}")
|
||||||
if (EASY_OPTION_LOW_PRIORITY_EVENT_TRACING)
|
message(STATUS " Event tracing has low priority = ${EASY_OPTION_LOW_PRIORITY_EVENT_TRACING}")
|
||||||
message(STATUS " Event tracing has low priority = Yes")
|
else ()
|
||||||
|
message(STATUS " WARNING! Implicit thread registration for Unix systems can lead to memory leak")
|
||||||
|
message(STATUS " because there is no possibility to check if thread is alive and remove dead threads.")
|
||||||
|
message(STATUS " Removing empty unguarded threads = ${EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS}")
|
||||||
|
if (EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS)
|
||||||
|
message(STATUS " WARNING! Removing empty unguarded threads may lead to an application crash!")
|
||||||
|
message(STATUS " But fixes potential memory leak on Unix systems.")
|
||||||
else ()
|
else ()
|
||||||
message(STATUS " Event tracing has low priority = No")
|
message(STATUS " WARNING! There is a possibility of memory leak without removing empty unguarded threads.")
|
||||||
endif (EASY_OPTION_LOW_PRIORITY_EVENT_TRACING)
|
endif ()
|
||||||
endif (WIN32)
|
message(STATUS " If implicit thread registration is OFF and your compiler supports C++11 thread_local feature")
|
||||||
|
message(STATUS " then You can ignore this warning. But beware if it's not so!")
|
||||||
|
endif ()
|
||||||
message(STATUS " Log messages = ${EASY_OPTION_LOG}")
|
message(STATUS " Log messages = ${EASY_OPTION_LOG}")
|
||||||
message(STATUS " Use EasyProfiler colors palette = ${EASY_OPTION_PREDEFINED_COLORS}")
|
message(STATUS " Use EasyProfiler colors palette = ${EASY_OPTION_PREDEFINED_COLORS}")
|
||||||
message(STATUS " Shared library: ${BUILD_SHARED_LIBS}")
|
message(STATUS " Shared library: ${BUILD_SHARED_LIBS}")
|
||||||
message(STATUS "------ END EASY_PROFILER OPTIONS -------")
|
message(STATUS "------ END EASY_PROFILER OPTIONS -------")
|
||||||
message(STATUS "")
|
message(STATUS "")
|
||||||
|
# End printing EasyProfiler options status.
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# Add source files:
|
||||||
set(CPP_FILES
|
set(CPP_FILES
|
||||||
block.cpp
|
block.cpp
|
||||||
profile_manager.cpp
|
profile_manager.cpp
|
||||||
@ -83,6 +117,11 @@ set(SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(easy_profiler ${SOURCES} resources.rc)
|
add_library(easy_profiler ${SOURCES} resources.rc)
|
||||||
|
# End adding source files.
|
||||||
|
#################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
target_include_directories(easy_profiler PUBLIC
|
target_include_directories(easy_profiler PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
$<INSTALL_INTERFACE:include> # <prefix>/include
|
$<INSTALL_INTERFACE:include> # <prefix>/include
|
||||||
@ -102,18 +141,31 @@ target_compile_definitions(easy_profiler PUBLIC
|
|||||||
-DBUILD_WITH_EASY_PROFILER=1
|
-DBUILD_WITH_EASY_PROFILER=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Add EasyProfiler options definitions:
|
||||||
easy_define_target_option(easy_profiler BUILD_WITH_CHRONO_STEADY_CLOCK EASY_CHRONO_STEADY_CLOCK)
|
easy_define_target_option(easy_profiler BUILD_WITH_CHRONO_STEADY_CLOCK EASY_CHRONO_STEADY_CLOCK)
|
||||||
easy_define_target_option(easy_profiler BUILD_WITH_CHRONO_HIGH_RESOLUTION_CLOCK EASY_CHRONO_HIGHRES_CLOCK)
|
easy_define_target_option(easy_profiler BUILD_WITH_CHRONO_HIGH_RESOLUTION_CLOCK EASY_CHRONO_HIGHRES_CLOCK)
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_LISTEN EASY_OPTION_START_LISTEN_ON_STARTUP)
|
easy_define_target_option(easy_profiler EASY_OPTION_LISTEN EASY_OPTION_START_LISTEN_ON_STARTUP)
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_PROFILE_SELF EASY_OPTION_MEASURE_STORAGE_EXPAND)
|
easy_define_target_option(easy_profiler EASY_OPTION_PROFILE_SELF EASY_OPTION_MEASURE_STORAGE_EXPAND)
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_PROFILE_SELF_BLOCKS_ON EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON)
|
easy_define_target_option(easy_profiler EASY_OPTION_PROFILE_SELF_BLOCKS_ON EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON)
|
||||||
|
easy_define_target_option(easy_profiler EASY_OPTION_IMPLICIT_THREAD_REGISTRATION EASY_OPTION_IMPLICIT_THREAD_REGISTRATION)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_EVENT_TRACING EASY_OPTION_EVENT_TRACING_ENABLED)
|
easy_define_target_option(easy_profiler EASY_OPTION_EVENT_TRACING EASY_OPTION_EVENT_TRACING_ENABLED)
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_LOW_PRIORITY_EVENT_TRACING EASY_OPTION_LOW_PRIORITY_EVENT_TRACING)
|
easy_define_target_option(easy_profiler EASY_OPTION_LOW_PRIORITY_EVENT_TRACING EASY_OPTION_LOW_PRIORITY_EVENT_TRACING)
|
||||||
|
else ()
|
||||||
|
easy_define_target_option(easy_profiler EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS)
|
||||||
endif ()
|
endif ()
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_LOG EASY_OPTION_LOG_ENABLED)
|
easy_define_target_option(easy_profiler EASY_OPTION_LOG EASY_OPTION_LOG_ENABLED)
|
||||||
easy_define_target_option(easy_profiler EASY_OPTION_PREDEFINED_COLORS EASY_OPTION_BUILTIN_COLORS)
|
easy_define_target_option(easy_profiler EASY_OPTION_PREDEFINED_COLORS EASY_OPTION_BUILTIN_COLORS)
|
||||||
|
# End adding EasyProfiler options definitions.
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Add platform specific compile options:
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_compile_options(easy_profiler PRIVATE -Wall -Wno-long-long -Wno-reorder -Wno-braced-scalar-init -pedantic)
|
target_compile_options(easy_profiler PRIVATE -Wall -Wno-long-long -Wno-reorder -Wno-braced-scalar-init -pedantic)
|
||||||
target_link_libraries(easy_profiler pthread)
|
target_link_libraries(easy_profiler pthread)
|
||||||
@ -128,29 +180,29 @@ endif ()
|
|||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
target_compile_options(easy_profiler PRIVATE /WX)
|
target_compile_options(easy_profiler PRIVATE /WX)
|
||||||
endif()
|
endif ()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
target_compile_options(easy_profiler PUBLIC -std=gnu++11)
|
target_compile_options(easy_profiler PUBLIC -std=gnu++11)
|
||||||
else ()
|
else ()
|
||||||
|
|
||||||
|
|
||||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
target_compile_options(easy_profiler PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-std=gnu++11>)
|
target_compile_options(easy_profiler PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-std=gnu++11>)
|
||||||
endif ()
|
endif ()
|
||||||
else()
|
else ()
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
target_compile_options(easy_profiler PUBLIC -std=gnu++11)
|
target_compile_options(easy_profiler PUBLIC -std=gnu++11)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
set_target_properties(easy_profiler PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
|
set_target_properties(easy_profiler PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
# End adding platform specific compile options.
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
####
|
|
||||||
# Installation
|
|
||||||
|
#########################################################################################
|
||||||
|
# Installation:
|
||||||
set(config_install_dir "lib/cmake/${PROJECT_NAME}")
|
set(config_install_dir "lib/cmake/${PROJECT_NAME}")
|
||||||
set(include_install_dir "include")
|
set(include_install_dir "include")
|
||||||
|
|
||||||
|
@ -225,6 +225,10 @@ EASY_THREAD_LOCAL static uint32_t THIS_THREAD_N_FRAMES = 0;
|
|||||||
EASY_THREAD_LOCAL static bool THIS_THREAD_FRAME_T_RESET_MAX = false;
|
EASY_THREAD_LOCAL static bool THIS_THREAD_FRAME_T_RESET_MAX = false;
|
||||||
EASY_THREAD_LOCAL static bool THIS_THREAD_FRAME_T_RESET_AVG = false;
|
EASY_THREAD_LOCAL static bool THIS_THREAD_FRAME_T_RESET_AVG = false;
|
||||||
|
|
||||||
|
#ifdef EASY_THREAD_LOCAL_CPP11
|
||||||
|
thread_local static profiler::ThreadGuard THIS_THREAD_GUARD; // thread guard for monitoring thread life time
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef BUILD_WITH_EASY_PROFILER
|
#ifdef BUILD_WITH_EASY_PROFILER
|
||||||
@ -686,7 +690,7 @@ void ThreadStorage::storeBlock(const profiler::Block& block)
|
|||||||
if (expanded) beginTime = getCurrentTime();
|
if (expanded) beginTime = getCurrentTime();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* data = (char*)blocks.closedList.allocate(size);
|
void* data = blocks.closedList.allocate(size);
|
||||||
|
|
||||||
#if EASY_OPTION_MEASURE_STORAGE_EXPAND != 0
|
#if EASY_OPTION_MEASURE_STORAGE_EXPAND != 0
|
||||||
if (expanded) endTime = getCurrentTime();
|
if (expanded) endTime = getCurrentTime();
|
||||||
@ -898,7 +902,7 @@ bool ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, cons
|
|||||||
}
|
}
|
||||||
else if (THIS_THREAD == nullptr)
|
else if (THIS_THREAD == nullptr)
|
||||||
{
|
{
|
||||||
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
registerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||||
@ -928,7 +932,7 @@ bool ProfileManager::storeBlock(const profiler::BaseBlockDescriptor* _desc, cons
|
|||||||
}
|
}
|
||||||
else if (THIS_THREAD == nullptr)
|
else if (THIS_THREAD == nullptr)
|
||||||
{
|
{
|
||||||
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
registerThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||||
@ -951,7 +955,7 @@ void ProfileManager::storeBlockForce(const profiler::BaseBlockDescriptor* _desc,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (THIS_THREAD == nullptr)
|
if (THIS_THREAD == nullptr)
|
||||||
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
registerThread();
|
||||||
|
|
||||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||||
if (!THIS_THREAD->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
if (!THIS_THREAD->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
||||||
@ -972,7 +976,7 @@ void ProfileManager::storeBlockForce2(const profiler::BaseBlockDescriptor* _desc
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (THIS_THREAD == nullptr)
|
if (THIS_THREAD == nullptr)
|
||||||
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
registerThread();
|
||||||
|
|
||||||
#if EASY_ENABLE_BLOCK_STATUS != 0
|
#if EASY_ENABLE_BLOCK_STATUS != 0
|
||||||
if (!THIS_THREAD->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
if (!THIS_THREAD->allowChildren && !(_desc->m_status & FORCE_ON_FLAG))
|
||||||
@ -997,7 +1001,7 @@ void ProfileManager::storeBlockForce2(ThreadStorage& _registeredThread, const pr
|
|||||||
void ProfileManager::beginBlock(Block& _block)
|
void ProfileManager::beginBlock(Block& _block)
|
||||||
{
|
{
|
||||||
if (THIS_THREAD == nullptr)
|
if (THIS_THREAD == nullptr)
|
||||||
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
registerThread();
|
||||||
|
|
||||||
if (++THIS_THREAD_STACK_SIZE > 1)
|
if (++THIS_THREAD_STACK_SIZE > 1)
|
||||||
{
|
{
|
||||||
@ -1075,7 +1079,7 @@ void ProfileManager::beginBlock(Block& _block)
|
|||||||
void ProfileManager::beginNonScopedBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName)
|
void ProfileManager::beginNonScopedBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName)
|
||||||
{
|
{
|
||||||
if (THIS_THREAD == nullptr)
|
if (THIS_THREAD == nullptr)
|
||||||
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
registerThread();
|
||||||
|
|
||||||
NonscopedBlock& b = THIS_THREAD->nonscopedBlocks.push(_desc, _runtimeName, false);
|
NonscopedBlock& b = THIS_THREAD->nonscopedBlocks.push(_desc, _runtimeName, false);
|
||||||
beginBlock(b);
|
beginBlock(b);
|
||||||
@ -1149,11 +1153,25 @@ void ProfileManager::endContextSwitch(profiler::thread_id_t _thread_id, processi
|
|||||||
{
|
{
|
||||||
ThreadStorage* ts = nullptr;
|
ThreadStorage* ts = nullptr;
|
||||||
if (_process_id == m_processId)
|
if (_process_id == m_processId)
|
||||||
|
{
|
||||||
|
// Implicit thread registration.
|
||||||
// If thread owned by current process then create new ThreadStorage if there is no one
|
// If thread owned by current process then create new ThreadStorage if there is no one
|
||||||
|
#if defined(EASY_OPTION_IMPLICIT_THREAD_REGISTRATION) && EASY_OPTION_IMPLICIT_THREAD_REGISTRATION != 0
|
||||||
ts = _lockSpin ? &threadStorage(_thread_id) : &_threadStorage(_thread_id);
|
ts = _lockSpin ? &threadStorage(_thread_id) : &_threadStorage(_thread_id);
|
||||||
|
# ifndef _WIN32
|
||||||
|
# if defined(EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS) && EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS != 0
|
||||||
|
# pragma message "Warning: Implicit thread registration may cause application crash because there is no possibility to check thread state (dead or alive) in Unix systems."
|
||||||
|
# else
|
||||||
|
# pragma message "Warning: Implicit thread registration may lead to memory leak because there is no possibility to check thread state (dead or alive) in Unix systems."
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// If thread owned by another process OR _process_id IS UNKNOWN then do not create ThreadStorage for this
|
// If thread owned by another process OR _process_id IS UNKNOWN then do not create ThreadStorage for this
|
||||||
ts = _lockSpin ? findThreadStorage(_thread_id) : _findThreadStorage(_thread_id);
|
ts = _lockSpin ? findThreadStorage(_thread_id) : _findThreadStorage(_thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
if (ts == nullptr || ts->sync.openedList.empty())
|
if (ts == nullptr || ts->sync.openedList.empty())
|
||||||
return;
|
return;
|
||||||
@ -1327,8 +1345,7 @@ char ProfileManager::checkThreadExpired(ThreadStorage& _registeredThread)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
// Check thread state for Windows
|
||||||
// Check thread for Windows
|
|
||||||
|
|
||||||
DWORD exitCode = 0;
|
DWORD exitCode = 0;
|
||||||
auto hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)_registeredThread.id);
|
auto hThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)_registeredThread.id);
|
||||||
@ -1345,13 +1362,20 @@ char ProfileManager::checkThreadExpired(ThreadStorage& _registeredThread)
|
|||||||
CloseHandle(hThread);
|
CloseHandle(hThread);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
// Check thread state for Linux and MacOS/iOS
|
||||||
|
|
||||||
return 0;//pthread_kill(_registeredThread.pthread_id, 0) != 0;
|
// This would drop the application if pthread already died
|
||||||
|
//return pthread_kill(_registeredThread.pthread_id, 0) != 0 ? 1 : 0;
|
||||||
|
|
||||||
|
// There is no function to check external pthread state in Linux! :((
|
||||||
|
|
||||||
|
#ifndef EASY_THREAD_LOCAL_CPP11
|
||||||
|
#pragma message "Warning: Your compiler does not support thread_local C++11 feature. Please use EASY_THREAD_SCOPE as much as possible. Otherwise, there is a possibility of memory leak if there are a lot of rapidly created and destroyed threads."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -1466,10 +1490,19 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream, bo
|
|||||||
{
|
{
|
||||||
auto& t = it->second;
|
auto& t = it->second;
|
||||||
uint32_t num = static_cast<uint32_t>(t.blocks.closedList.size()) + static_cast<uint32_t>(t.sync.closedList.size());
|
uint32_t num = static_cast<uint32_t>(t.blocks.closedList.size()) + static_cast<uint32_t>(t.sync.closedList.size());
|
||||||
|
const char expired = ProfileManager::checkThreadExpired(t);
|
||||||
|
|
||||||
const char expired = checkThreadExpired(t);
|
#if !defined(_WIN32) && defined(EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS) && EASY_OPTION_REMOVE_EMPTY_UNGUARDED_THREADS != 0
|
||||||
if (num == 0 && (expired != 0 || !t.guarded)) {
|
#pragma message "Warning: Removing !guarded thread may cause an application crash, but fixes potential memory leak on Unix systems."
|
||||||
// Remove thread if it contains no profiled information and has been finished or is not guarded.
|
if (num == 0 && (expired != 0
|
||||||
|
|| !t.guarded)) // Removing !guarded thread may cause an application crash if a thread would start to write blocks after ThreadStorage remove.
|
||||||
|
|
||||||
|
// TODO: Find solution to check thread state on Unix systems or to nullify THIS_THREAD pointer for removed ThreadStorage
|
||||||
|
#else
|
||||||
|
if (num == 0 && expired != 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Remove thread if it contains no profiled information and has been finished (or is not guarded --deprecated).
|
||||||
profiler::thread_id_t id = it->first;
|
profiler::thread_id_t id = it->first;
|
||||||
if (!mainThreadExpired && m_mainThreadId.compare_exchange_weak(id, 0, std::memory_order_release, std::memory_order_acquire))
|
if (!mainThreadExpired && m_mainThreadId.compare_exchange_weak(id, 0, std::memory_order_release, std::memory_order_acquire))
|
||||||
mainThreadExpired = true;
|
mainThreadExpired = true;
|
||||||
@ -1477,7 +1510,8 @@ uint32_t ProfileManager::dumpBlocksToStream(profiler::OStream& _outputStream, bo
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expired == 1) {
|
if (expired == 1)
|
||||||
|
{
|
||||||
EASY_FORCE_EVENT3(t, endtime, "ThreadExpired", EASY_COLOR_THREAD_END);
|
EASY_FORCE_EVENT3(t, endtime, "ThreadExpired", EASY_COLOR_THREAD_END);
|
||||||
++num;
|
++num;
|
||||||
}
|
}
|
||||||
@ -1605,6 +1639,16 @@ uint32_t ProfileManager::dumpBlocksToFile(const char* _filename)
|
|||||||
return blocksNumber;
|
return blocksNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProfileManager::registerThread()
|
||||||
|
{
|
||||||
|
THIS_THREAD = &threadStorage(getCurrentThreadId());
|
||||||
|
|
||||||
|
#ifdef EASY_THREAD_LOCAL_CPP11
|
||||||
|
THIS_THREAD->guarded = true;
|
||||||
|
THIS_THREAD_GUARD.m_id = THIS_THREAD->id;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
const char* ProfileManager::registerThread(const char* name, ThreadGuard& threadGuard)
|
const char* ProfileManager::registerThread(const char* name, ThreadGuard& threadGuard)
|
||||||
{
|
{
|
||||||
if (THIS_THREAD == nullptr)
|
if (THIS_THREAD == nullptr)
|
||||||
@ -1621,9 +1665,17 @@ const char* ProfileManager::registerThread(const char* name, ThreadGuard& thread
|
|||||||
profiler::thread_id_t id = 0;
|
profiler::thread_id_t id = 0;
|
||||||
THIS_THREAD_IS_MAIN = m_mainThreadId.compare_exchange_weak(id, THIS_THREAD->id, std::memory_order_release, std::memory_order_acquire);
|
THIS_THREAD_IS_MAIN = m_mainThreadId.compare_exchange_weak(id, THIS_THREAD->id, std::memory_order_release, std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EASY_THREAD_LOCAL_CPP11
|
||||||
|
THIS_THREAD_GUARD.m_id = THIS_THREAD->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
threadGuard; // this is just to prevent from warning about unused variable
|
||||||
|
#else
|
||||||
}
|
}
|
||||||
|
|
||||||
threadGuard.m_id = THIS_THREAD->id;
|
threadGuard.m_id = THIS_THREAD->id;
|
||||||
|
#endif
|
||||||
|
|
||||||
return THIS_THREAD->name.c_str();
|
return THIS_THREAD->name.c_str();
|
||||||
}
|
}
|
||||||
@ -1643,6 +1695,11 @@ const char* ProfileManager::registerThread(const char* name)
|
|||||||
profiler::thread_id_t id = 0;
|
profiler::thread_id_t id = 0;
|
||||||
THIS_THREAD_IS_MAIN = m_mainThreadId.compare_exchange_weak(id, THIS_THREAD->id, std::memory_order_release, std::memory_order_acquire);
|
THIS_THREAD_IS_MAIN = m_mainThreadId.compare_exchange_weak(id, THIS_THREAD->id, std::memory_order_release, std::memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef EASY_THREAD_LOCAL_CPP11
|
||||||
|
THIS_THREAD->guarded = true;
|
||||||
|
THIS_THREAD_GUARD.m_id = THIS_THREAD->id;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return THIS_THREAD->name.c_str();
|
return THIS_THREAD->name.c_str();
|
||||||
|
@ -3,40 +3,40 @@ Lightweight profiler library for c++
|
|||||||
Copyright(C) 2016-2017 Sergey Yagovtsev, Victor Zarubkin
|
Copyright(C) 2016-2017 Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
|
||||||
Licensed under either of
|
Licensed under either of
|
||||||
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||||
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
at your option.
|
at your option.
|
||||||
|
|
||||||
The MIT License
|
The MIT License
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
of the Software, and to permit persons to whom the Software is furnished
|
of the Software, and to permit persons to whom the Software is furnished
|
||||||
to do so, subject to the following conditions:
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
The Apache License, Version 2.0 (the "License");
|
The Apache License, Version 2.0 (the "License");
|
||||||
You may not use this file except in compliance with the License.
|
You may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@ -368,29 +368,28 @@ EASY_FORCE_INLINE T unaligned_load64(const void* ptr, T* val)
|
|||||||
template <uint16_t N>
|
template <uint16_t N>
|
||||||
class chunk_allocator
|
class chunk_allocator
|
||||||
{
|
{
|
||||||
struct chunk { EASY_ALIGNED(int8_t, data[N], EASY_ALIGNMENT_SIZE); chunk* prev = nullptr; };
|
struct chunk { EASY_ALIGNED(char, data[N], EASY_ALIGNMENT_SIZE); chunk* prev = nullptr; };
|
||||||
|
|
||||||
struct chunk_list
|
struct chunk_list
|
||||||
{
|
{
|
||||||
chunk* last = nullptr;
|
chunk* last;
|
||||||
|
|
||||||
|
chunk_list() : last(nullptr)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(char) == 1, "easy_profiler logic error: sizeof(char) != 1 for this platform! Please, contact easy_profiler authors to resolve your problem.");
|
||||||
|
emplace_back();
|
||||||
|
}
|
||||||
|
|
||||||
~chunk_list()
|
~chunk_list()
|
||||||
{
|
{
|
||||||
clear();
|
do free_last(); while (last != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear_all_except_last()
|
||||||
{
|
{
|
||||||
do {
|
while (last->prev != nullptr)
|
||||||
auto p = last;
|
free_last();
|
||||||
last = last->prev;
|
zero_last_chunk_size();
|
||||||
EASY_FREE(p);
|
|
||||||
} while (last != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk& back()
|
|
||||||
{
|
|
||||||
return *last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void emplace_back()
|
void emplace_back()
|
||||||
@ -398,12 +397,7 @@ class chunk_allocator
|
|||||||
auto prev = last;
|
auto prev = last;
|
||||||
last = ::new (EASY_MALLOC(sizeof(chunk), EASY_ALIGNMENT_SIZE)) chunk();
|
last = ::new (EASY_MALLOC(sizeof(chunk), EASY_ALIGNMENT_SIZE)) chunk();
|
||||||
last->prev = prev;
|
last->prev = prev;
|
||||||
// Although there is no need for unaligned access stuff b/c a new chunk will
|
zero_last_chunk_size();
|
||||||
// usually be at least 8 byte aligned (and we only need 2 byte alignment),
|
|
||||||
// this is the only way I have been able to get rid of the GCC strict-aliasing warning
|
|
||||||
// without using std::memset. It's an extra line, but is just as fast as *(uint16_t*)last->data = 0;
|
|
||||||
char* const data = (char*)&last->data;
|
|
||||||
*(uint16_t*)data = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invert current chunks list to enable to iterate over chunks list in direct order.
|
/** Invert current chunks list to enable to iterate over chunks list in direct order.
|
||||||
@ -423,12 +417,33 @@ class chunk_allocator
|
|||||||
|
|
||||||
last->prev = next;
|
last->prev = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
chunk_list(const chunk_list&) = delete;
|
||||||
|
chunk_list(chunk_list&&) = delete;
|
||||||
|
|
||||||
|
void free_last()
|
||||||
|
{
|
||||||
|
auto p = last;
|
||||||
|
last = last->prev;
|
||||||
|
EASY_FREE(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zero_last_chunk_size()
|
||||||
|
{
|
||||||
|
// Although there is no need for unaligned access stuff b/c a new chunk will
|
||||||
|
// usually be at least 8 byte aligned (and we only need 2 byte alignment),
|
||||||
|
// this is the only way I have been able to get rid of the GCC strict-aliasing warning
|
||||||
|
// without using std::memset. It's an extra line, but is just as fast as *(uint16_t*)last->data = 0;
|
||||||
|
char* const data = last->data;
|
||||||
|
*(uint16_t*)data = (uint16_t)0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//typedef std::list<chunk> chunk_list;
|
|
||||||
|
|
||||||
// Used in serialize(): workaround for no constexpr support in MSVC 2013.
|
// Used in serialize(): workaround for no constexpr support in MSVC 2013.
|
||||||
static const int_fast32_t MAX_CHUNK_OFFSET = N-sizeof(uint16_t);
|
static const int_fast32_t MAX_CHUNK_OFFSET = N - sizeof(uint16_t);
|
||||||
|
static const uint16_t N_MINUS_ONE = N - 1;
|
||||||
|
|
||||||
chunk_list m_chunks; ///< List of chunks.
|
chunk_list m_chunks; ///< List of chunks.
|
||||||
uint32_t m_size; ///< Number of elements stored(# of times allocate() has been called.)
|
uint32_t m_size; ///< Number of elements stored(# of times allocate() has been called.)
|
||||||
@ -438,7 +453,6 @@ public:
|
|||||||
|
|
||||||
chunk_allocator() : m_size(0), m_chunkOffset(0)
|
chunk_allocator() : m_size(0), m_chunkOffset(0)
|
||||||
{
|
{
|
||||||
m_chunks.emplace_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocate n bytes.
|
/** Allocate n bytes.
|
||||||
@ -454,7 +468,7 @@ public:
|
|||||||
{
|
{
|
||||||
// Temp to avoid extra load due to this* aliasing.
|
// Temp to avoid extra load due to this* aliasing.
|
||||||
uint16_t chunkOffset = m_chunkOffset;
|
uint16_t chunkOffset = m_chunkOffset;
|
||||||
char* data = (char*)m_chunks.back().data + chunkOffset;
|
char* data = m_chunks.last->data + chunkOffset;
|
||||||
chunkOffset += n + sizeof(uint16_t);
|
chunkOffset += n + sizeof(uint16_t);
|
||||||
m_chunkOffset = chunkOffset;
|
m_chunkOffset = chunkOffset;
|
||||||
|
|
||||||
@ -463,7 +477,7 @@ public:
|
|||||||
|
|
||||||
// If there is enough space for at least another payload size,
|
// If there is enough space for at least another payload size,
|
||||||
// set it to zero.
|
// set it to zero.
|
||||||
if (chunkOffset < N-1)
|
if (chunkOffset < N_MINUS_ONE)
|
||||||
unaligned_zero16(data + n);
|
unaligned_zero16(data + n);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@ -472,7 +486,7 @@ public:
|
|||||||
m_chunkOffset = n + sizeof(uint16_t);
|
m_chunkOffset = n + sizeof(uint16_t);
|
||||||
m_chunks.emplace_back();
|
m_chunks.emplace_back();
|
||||||
|
|
||||||
char* data = (char*)&m_chunks.back().data[0];
|
char* data = m_chunks.last->data;
|
||||||
unaligned_store16(data, n);
|
unaligned_store16(data, n);
|
||||||
data += sizeof(uint16_t);
|
data += sizeof(uint16_t);
|
||||||
|
|
||||||
@ -503,8 +517,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
m_chunkOffset = 0;
|
m_chunkOffset = 0;
|
||||||
m_chunks.clear();
|
m_chunks.clear_all_except_last(); // There is always at least one chunk
|
||||||
m_chunks.emplace_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Serialize data to stream.
|
/** Serialize data to stream.
|
||||||
@ -529,10 +542,10 @@ public:
|
|||||||
|
|
||||||
chunk* current = m_chunks.last;
|
chunk* current = m_chunks.last;
|
||||||
do {
|
do {
|
||||||
const char* data = (char*)current->data;
|
const char* data = current->data;
|
||||||
int_fast32_t chunkOffset = 0; // signed int so overflow is not checked.
|
int_fast32_t chunkOffset = 0; // signed int so overflow is not checked.
|
||||||
uint16_t payloadSize = unaligned_load16<uint16_t>(data);
|
uint16_t payloadSize = unaligned_load16<uint16_t>(data);
|
||||||
while ((chunkOffset < MAX_CHUNK_OFFSET) & (payloadSize != 0)) {
|
while (chunkOffset < MAX_CHUNK_OFFSET && payloadSize != 0) {
|
||||||
const uint16_t chunkSize = sizeof(uint16_t) + payloadSize;
|
const uint16_t chunkSize = sizeof(uint16_t) + payloadSize;
|
||||||
_outputStream.write(data, chunkSize);
|
_outputStream.write(data, chunkSize);
|
||||||
data += chunkSize;
|
data += chunkSize;
|
||||||
@ -546,6 +559,11 @@ public:
|
|||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
chunk_allocator(const chunk_allocator&) = delete;
|
||||||
|
chunk_allocator(chunk_allocator&&) = delete;
|
||||||
|
|
||||||
}; // END of class chunk_allocator.
|
}; // END of class chunk_allocator.
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -652,6 +670,11 @@ public:
|
|||||||
m_overflow.pop_back();
|
m_overflow.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
StackBuffer(const StackBuffer&) = delete;
|
||||||
|
StackBuffer(StackBuffer&&) = delete;
|
||||||
|
|
||||||
}; // END of class StackBuffer.
|
}; // END of class StackBuffer.
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -670,6 +693,11 @@ struct BlocksList
|
|||||||
usedMemorySize = 0;
|
usedMemorySize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
BlocksList(const BlocksList&) = delete;
|
||||||
|
BlocksList(BlocksList&&) = delete;
|
||||||
|
|
||||||
}; // END of struct BlocksList.
|
}; // END of struct BlocksList.
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -715,6 +743,11 @@ struct ThreadStorage
|
|||||||
|
|
||||||
ThreadStorage();
|
ThreadStorage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ThreadStorage(const ThreadStorage&) = delete;
|
||||||
|
ThreadStorage(ThreadStorage&&) = delete;
|
||||||
|
|
||||||
}; // END of struct ThreadStorage.
|
}; // END of struct ThreadStorage.
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -822,13 +855,15 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void registerThread();
|
||||||
|
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
void endFrame();
|
void endFrame();
|
||||||
|
|
||||||
void enableEventTracer();
|
void enableEventTracer();
|
||||||
void disableEventTracer();
|
void disableEventTracer();
|
||||||
|
|
||||||
char checkThreadExpired(ThreadStorage& _registeredThread);
|
static char checkThreadExpired(ThreadStorage& _registeredThread);
|
||||||
|
|
||||||
void storeBlockForce(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t& _timestamp);
|
void storeBlockForce(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t& _timestamp);
|
||||||
void storeBlockForce2(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t _timestamp);
|
void storeBlockForce2(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, ::profiler::timestamp_t _timestamp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user