timemory submodule (#1)
- library now wraps fork() to warn about fork + OpenMPI
[ROCm/rocprofiler-systems commit: fc7cc1e68f]
This commit is contained in:
کامیت شده توسط
GitHub
والد
3d3270b214
کامیت
045f29eda6
@@ -0,0 +1,6 @@
|
||||
[submodule "external/timemory"]
|
||||
path = external/timemory
|
||||
url = https://github.com/NERSC/timemory.git
|
||||
[submodule "external/perfetto"]
|
||||
path = external/perfetto
|
||||
url = https://android.googlesource.com/platform/external/perfetto
|
||||
@@ -11,7 +11,7 @@ endif()
|
||||
|
||||
project(
|
||||
hosttrace
|
||||
LANGUAGES CXX
|
||||
LANGUAGES C CXX
|
||||
VERSION 0.0.1)
|
||||
|
||||
message(STATUS "[${PROJECT_NAME}] version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
@@ -41,6 +41,8 @@ hosttrace_activate_clang_tidy()
|
||||
#
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
option(HOSTTRACE_CUSTOM_DATA_SOURCE "Enable custom data source" OFF)
|
||||
|
||||
add_library(hosttrace-library SHARED
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
|
||||
${perfetto_DIR}/sdk/perfetto.cc)
|
||||
@@ -51,8 +53,13 @@ target_include_directories(hosttrace-library PRIVATE
|
||||
target_include_directories(hosttrace-library SYSTEM PRIVATE
|
||||
${perfetto_DIR}/sdk)
|
||||
|
||||
target_compile_definitions(hosttrace-library PRIVATE
|
||||
$<IF:$<BOOL:${HOSTTRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
|
||||
|
||||
target_link_libraries(hosttrace-library PRIVATE
|
||||
hosttrace::hosttrace-threading
|
||||
$<BUILD_INTERFACE:timemory::timemory-headers>
|
||||
$<BUILD_INTERFACE:timemory::timemory-gotcha>
|
||||
$<IF:$<BOOL:${hosttrace_USE_SANITIZER}>,hosttrace::hosttrace-sanitizer,>)
|
||||
|
||||
set_target_properties(hosttrace-library PROPERTIES
|
||||
@@ -78,6 +85,7 @@ target_include_directories(hosttrace-exe PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
|
||||
target_link_libraries(hosttrace-exe PRIVATE
|
||||
$<BUILD_INTERFACE:timemory::timemory-headers>
|
||||
hosttrace::hosttrace-dyninst
|
||||
hosttrace::hosttrace-compile-options)
|
||||
|
||||
@@ -90,35 +98,6 @@ install(
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
OPTIONAL)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
#
|
||||
# clang-format target
|
||||
#
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
find_program(CLANG_FORMAT_EXE
|
||||
NAMES
|
||||
clang-format-12
|
||||
clang-format-11
|
||||
clang-format-10
|
||||
clang-format-9
|
||||
clang-format)
|
||||
|
||||
if(CLANG_FORMAT_EXE)
|
||||
file(GLOB sources
|
||||
${PROJECT_SOURCE_DIR}/src/*.cpp)
|
||||
file(GLOB headers
|
||||
${PROJECT_SOURCE_DIR}/include/*.hpp)
|
||||
file(GLOB_RECURSE examples
|
||||
${PROJECT_SOURCE_DIR}/examples/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/examples/*.hpp)
|
||||
add_custom_target(format
|
||||
${CLANG_FORMAT_EXE} -i ${sources} ${headers} ${examples}
|
||||
COMMENT "Running ${CLANG_FORMAT_EXE}...")
|
||||
else()
|
||||
message(AUTHOR_WARNING "clang-format could not be found. format build target not available.")
|
||||
endif()
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
#
|
||||
# examples
|
||||
|
||||
@@ -94,12 +94,12 @@ endmacro(set_no_duplicates _VAR)
|
||||
#----------------------------------------------------------------------------------------#
|
||||
# call before running check_{c,cxx}_compiler_flag
|
||||
#----------------------------------------------------------------------------------------#
|
||||
macro(timemory_begin_flag_check)
|
||||
if(TIMEMORY_QUIET_CONFIG)
|
||||
macro(hosttrace_begin_flag_check)
|
||||
if(HOSTTRACE_QUIET_CONFIG)
|
||||
if(NOT DEFINED CMAKE_REQUIRED_QUIET)
|
||||
set(CMAKE_REQUIRED_QUIET OFF)
|
||||
endif()
|
||||
timemory_save_variables(FLAG_CHECK
|
||||
hosttrace_save_variables(FLAG_CHECK
|
||||
VARIABLES CMAKE_REQUIRED_QUIET)
|
||||
set(CMAKE_REQUIRED_QUIET ON)
|
||||
endif()
|
||||
@@ -108,9 +108,9 @@ endmacro()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
# call after running check_{c,cxx}_compiler_flag
|
||||
#----------------------------------------------------------------------------------------#
|
||||
macro(timemory_end_flag_check)
|
||||
if(TIMEMORY_QUIET_CONFIG)
|
||||
timemory_restore_variables(FLAG_CHECK
|
||||
macro(hosttrace_end_flag_check)
|
||||
if(HOSTTRACE_QUIET_CONFIG)
|
||||
hosttrace_restore_variables(FLAG_CHECK
|
||||
VARIABLES CMAKE_REQUIRED_QUIET)
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -127,7 +127,7 @@ endmacro()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
macro(ADD_TARGET_C_FLAG _TARG)
|
||||
string(REPLACE "-" "_" _MAKE_TARG "${_TARG}")
|
||||
list(APPEND TIMEMORY_MAKE_TARGETS ${_MAKE_TARG})
|
||||
list(APPEND HOSTTRACE_MAKE_TARGETS ${_MAKE_TARG})
|
||||
|
||||
target_compile_options(${_TARG} INTERFACE $<$<COMPILE_LANGUAGE:C>:${ARGN}>)
|
||||
list(APPEND ${_MAKE_TARG}_C_FLAGS ${ARGN})
|
||||
@@ -163,7 +163,7 @@ endmacro()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
macro(ADD_C_FLAG_IF_AVAIL FLAG)
|
||||
set(_ENABLE ON)
|
||||
if(DEFINED TIMEMORY_BUILD_C AND NOT TIMEMORY_BUILD_C)
|
||||
if(DEFINED HOSTTRACE_BUILD_C AND NOT HOSTTRACE_BUILD_C)
|
||||
set(_ENABLE OFF)
|
||||
endif()
|
||||
set(_TARG )
|
||||
@@ -178,17 +178,17 @@ macro(ADD_C_FLAG_IF_AVAIL FLAG)
|
||||
string(REPLACE "-" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE " " "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE "=" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
if(NOT TIMEMORY_BUILD_C)
|
||||
if(NOT HOSTTRACE_BUILD_C)
|
||||
set(${FLAG_NAME} ON)
|
||||
else()
|
||||
timemory_begin_flag_check()
|
||||
hosttrace_begin_flag_check()
|
||||
check_c_compiler_flag("-Werror" c_werror)
|
||||
if(c_werror)
|
||||
check_c_compiler_flag("${FLAG} -Werror" ${FLAG_NAME})
|
||||
else()
|
||||
check_c_compiler_flag("${FLAG}" ${FLAG_NAME})
|
||||
endif()
|
||||
timemory_end_flag_check()
|
||||
hosttrace_end_flag_check()
|
||||
if(${FLAG_NAME})
|
||||
if("${_LTARG}" STREQUAL "")
|
||||
list(APPEND ${PROJECT_NAME}_C_FLAGS "${FLAG}")
|
||||
@@ -228,7 +228,7 @@ endmacro()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
macro(ADD_TARGET_CXX_FLAG _TARG)
|
||||
string(REPLACE "-" "_" _MAKE_TARG "${_TARG}")
|
||||
list(APPEND TIMEMORY_MAKE_TARGETS ${_MAKE_TARG})
|
||||
list(APPEND HOSTTRACE_MAKE_TARGETS ${_MAKE_TARG})
|
||||
|
||||
target_compile_options(${_TARG} INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${ARGN}>)
|
||||
list(APPEND ${_MAKE_TARG}_CXX_FLAGS ${ARGN})
|
||||
@@ -284,14 +284,14 @@ macro(ADD_CXX_FLAG_IF_AVAIL FLAG)
|
||||
string(REPLACE " " "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE "=" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE "/" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
timemory_begin_flag_check()
|
||||
hosttrace_begin_flag_check()
|
||||
check_cxx_compiler_flag("-Werror" cxx_werror)
|
||||
if(cxx_werror)
|
||||
check_cxx_compiler_flag("${FLAG} -Werror" ${FLAG_NAME})
|
||||
else()
|
||||
check_cxx_compiler_flag("${FLAG}" ${FLAG_NAME})
|
||||
endif()
|
||||
timemory_end_flag_check()
|
||||
hosttrace_end_flag_check()
|
||||
if(${FLAG_NAME})
|
||||
if("${_LTARG}" STREQUAL "")
|
||||
list(APPEND ${PROJECT_NAME}_CXX_FLAGS "${FLAG}")
|
||||
@@ -371,7 +371,7 @@ endmacro()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
# check flag
|
||||
#----------------------------------------------------------------------------------------#
|
||||
function(TIMEMORY_TARGET_FLAG _TARG_TARGET)
|
||||
function(HOSTTRACE_TARGET_FLAG _TARG_TARGET)
|
||||
cmake_parse_arguments(_TARG "IF_AVAIL" "MODE" "FLAGS;LANGUAGES" ${ARGN})
|
||||
|
||||
if(NOT _TARG_MODE)
|
||||
@@ -399,14 +399,14 @@ function(TIMEMORY_TARGET_FLAG _TARG_TARGET)
|
||||
string(REPLACE "-" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE " " "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE "=" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
timemory_begin_flag_check()
|
||||
hosttrace_begin_flag_check()
|
||||
check_c_compiler_flag("-Werror" c_werror)
|
||||
if(c_werror)
|
||||
check_c_compiler_flag("${FLAG} -Werror" ${FLAG_NAME})
|
||||
else()
|
||||
check_c_compiler_flag("${FLAG}" ${FLAG_NAME})
|
||||
endif()
|
||||
timemory_end_flag_check()
|
||||
hosttrace_end_flag_check()
|
||||
if(${FLAG_NAME})
|
||||
target_compile_options(${_TARG_TARGET} ${_TARG_MODE}
|
||||
$<$<COMPILE_LANGUAGE:${_LANG}>:${_FLAG}>)
|
||||
@@ -417,14 +417,14 @@ function(TIMEMORY_TARGET_FLAG _TARG_TARGET)
|
||||
string(REPLACE "-" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE " " "_" FLAG_NAME "${FLAG_NAME}")
|
||||
string(REPLACE "=" "_" FLAG_NAME "${FLAG_NAME}")
|
||||
timemory_begin_flag_check()
|
||||
hosttrace_begin_flag_check()
|
||||
check_cxx_compiler_flag("-Werror" cxx_werror)
|
||||
if(cxx_werror)
|
||||
check_cxx_compiler_flag("${FLAG} -Werror" ${FLAG_NAME})
|
||||
else()
|
||||
check_cxx_compiler_flag("${FLAG}" ${FLAG_NAME})
|
||||
endif()
|
||||
timemory_end_flag_check()
|
||||
hosttrace_end_flag_check()
|
||||
if(${FLAG_NAME})
|
||||
target_compile_options(${_TARG_TARGET} ${_TARG_MODE}
|
||||
$<$<COMPILE_LANGUAGE:${_LANG}>:${_FLAG}>)
|
||||
@@ -447,7 +447,7 @@ endfunction()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
macro(ADD_TARGET_CUDA_FLAG _TARG)
|
||||
string(REPLACE "-" "_" _MAKE_TARG "${_TARG}")
|
||||
list(APPEND TIMEMORY_MAKE_TARGETS ${_MAKE_TARG})
|
||||
list(APPEND HOSTTRACE_MAKE_TARGETS ${_MAKE_TARG})
|
||||
|
||||
target_compile_options(${_TARG} INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:${ARGN}>)
|
||||
list(APPEND ${_MAKE_TARG}_CUDA_FLAGS ${ARGN})
|
||||
@@ -476,7 +476,7 @@ endfunction()
|
||||
#----------------------------------------------------------------------------------------#
|
||||
# add compiler definition
|
||||
#----------------------------------------------------------------------------------------#
|
||||
function(TIMEMORY_TARGET_COMPILE_DEFINITIONS _TARG _VIS)
|
||||
function(HOSTTRACE_TARGET_COMPILE_DEFINITIONS _TARG _VIS)
|
||||
foreach(_DEF ${ARGN})
|
||||
target_compile_definitions(${_TARG} ${_VIS}
|
||||
$<$<COMPILE_LANGUAGE:CXX>:${_DEF}>)
|
||||
|
||||
@@ -121,12 +121,13 @@ endif()
|
||||
#
|
||||
#----------------------------------------------------------------------------------------#
|
||||
|
||||
set(perfetto_DIR ${PROJECT_BINARY_DIR}/stuff/hosttrace-dyninst/perfetto)
|
||||
if(NOT EXISTS "${perfetto_DIR}/.git")
|
||||
find_package(Git REQUIRED)
|
||||
execute_process(COMMAND
|
||||
${GIT_EXECUTABLE} clone -b v17.0 https://android.googlesource.com/platform/external/perfetto/ ${perfetto_DIR})
|
||||
endif()
|
||||
set(perfetto_DIR ${PROJECT_SOURCE_DIR}/external/perfetto)
|
||||
checkout_git_submodule(
|
||||
RELATIVE_PATH external/perfetto
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
REPO_URL https://android.googlesource.com/platform/external/perfetto
|
||||
REPO_BRANCH v17.0
|
||||
TEST_FILE sdk/perfetto.cc)
|
||||
|
||||
#----------------------------------------------------------------------------------------#
|
||||
#
|
||||
@@ -157,3 +158,57 @@ macro(HOSTTRACE_ACTIVATE_CLANG_TIDY)
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
#
|
||||
# clang-format target
|
||||
#
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
find_program(CLANG_FORMAT_EXE
|
||||
NAMES
|
||||
clang-format-12
|
||||
clang-format-11
|
||||
clang-format-10
|
||||
clang-format-9
|
||||
clang-format)
|
||||
|
||||
if(CLANG_FORMAT_EXE)
|
||||
file(GLOB sources
|
||||
${PROJECT_SOURCE_DIR}/src/*.cpp)
|
||||
file(GLOB headers
|
||||
${PROJECT_SOURCE_DIR}/include/*.hpp)
|
||||
file(GLOB_RECURSE examples
|
||||
${PROJECT_SOURCE_DIR}/examples/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/examples/*.hpp)
|
||||
add_custom_target(format
|
||||
${CLANG_FORMAT_EXE} -i ${sources} ${headers} ${examples}
|
||||
COMMENT "Running ${CLANG_FORMAT_EXE}...")
|
||||
else()
|
||||
message(AUTHOR_WARNING "clang-format could not be found. format build target not available.")
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------------------------#
|
||||
# configure submodule
|
||||
#----------------------------------------------------------------------------------------#
|
||||
|
||||
set(TIMEMORY_INSTALL_HEADERS OFF CACHE BOOL "Disable timemory header install")
|
||||
set(TIMEMORY_INSTALL_CONFIG OFF CACHE BOOL "Disable timemory cmake configuration install")
|
||||
set(TIMEMORY_INSTALL_ALL OFF CACHE BOOL "Disable install target depending on all target")
|
||||
set(TIMEMORY_BUILD_TOOLS OFF CACHE BOOL "Ensure timem executable is built")
|
||||
set(TIMEMORY_BUILD_EXCLUDE_FROM_ALL ON CACHE BOOL "Set timemory to only build dependencies")
|
||||
set(TIMEMORY_QUIET_CONFIG ON CACHE BOOL "Make timemory configuration quieter")
|
||||
|
||||
# timemory feature settings
|
||||
set(TIMEMORY_USE_GOTCHA ON CACHE BOOL "Enable GOTCHA support in timemory")
|
||||
set(TIMEMORY_USE_PERFETTO OFF CACHE BOOL "Disable perfetto support in timemory")
|
||||
# timemory feature build settings
|
||||
set(TIMEMORY_BUILD_GOTCHA ON CACHE BOOL "Enable building GOTCHA library from submodule")
|
||||
|
||||
checkout_git_submodule(
|
||||
RELATIVE_PATH external/timemory
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
REPO_URL https://github.com/NERSC/timemory.git
|
||||
REPO_BRANCH develop)
|
||||
|
||||
add_subdirectory(external/timemory)
|
||||
|
||||
@@ -20,6 +20,7 @@ endif()
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
|
||||
set(transpose_CXX_FLAGS "-W -Wall ${CMAKE_CXX_FLAGS_${BUILD_TYPE}} ${CMAKE_CXX_FLAGS}")
|
||||
set(transpose_LINK_FLAGS "")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_IS_CLANG AND TARGET hosttrace::hosttrace-compile-options)
|
||||
set(transpose_CXX_FLAGS "${transpose_CXX_FLAGS} ${hosttrace_CXX_FLAGS}")
|
||||
@@ -27,6 +28,40 @@ if(CMAKE_CXX_COMPILER_IS_CLANG AND TARGET hosttrace::hosttrace-compile-options)
|
||||
set(transpose_CXX_FLAGS "${transpose_CXX_FLAGS} ${COMPILE_OPTS}")
|
||||
endif()
|
||||
|
||||
option(TRANSPOSE_USE_MPI "Enable MPI support in transpose exe" ${TIMEMORY_USE_MPI})
|
||||
|
||||
if(TRANSPOSE_USE_MPI)
|
||||
find_package(MPI REQUIRED)
|
||||
endif()
|
||||
|
||||
if(TARGET MPI::MPI_C)
|
||||
set(transpose_CXX_FLAGS "${transpose_CXX_FLAGS} -DUSE_MPI")
|
||||
get_target_property(COMPILE_OPTS MPI::MPI_C INTERFACE_COMPILE_OPTIONS)
|
||||
foreach(_COPT ${COMPILE_OPTS})
|
||||
if(NOT "${_COPT}" MATCHES "COMPILE_LANG")
|
||||
set(transpose_CXX_FLAGS "${transpose_CXX_FLAGS} ${_COPT}")
|
||||
endif()
|
||||
endforeach()
|
||||
get_target_property(INCLUDE_DIRS MPI::MPI_C INTERFACE_INCLUDE_DIRECTORIES)
|
||||
foreach(_IDIR ${INCLUDE_DIRS})
|
||||
set(transpose_CXX_FLAGS "${transpose_CXX_FLAGS} -I${_IDIR}")
|
||||
get_filename_component(_LIBDIR "${_IDIR}" DIRECTORY)
|
||||
foreach(_LDIR lib lib64)
|
||||
set(_LIBDIR_SAVE "${_LIBDIR}")
|
||||
if(NOT EXISTS "${_LIBDIR}/${_LDIR}")
|
||||
get_filename_component(_LIBDIR "${_LIBDIR}" DIRECTORY)
|
||||
endif()
|
||||
if(EXISTS "${_LIBDIR}/${_LDIR}")
|
||||
set(transpose_LINK_FLAGS "${transpose_LINK_FLAGS} -L${_LIBDIR}/${_LDIR} -lmpi")
|
||||
endif()
|
||||
set(_LIBDIR "${_LIBDIR_SAVE}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
if(MPI_C_LINK_FLAGS)
|
||||
set(transpose_LINK_FLAGS "${transpose_LINK_FLAGS} ${MPI_C_LINK_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# remove generator expressions
|
||||
string(REPLACE "$<" "" transpose_CXX_FLAGS "${transpose_CXX_FLAGS}")
|
||||
string(REPLACE ">:" ":" transpose_CXX_FLAGS "${transpose_CXX_FLAGS}")
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
CXXFLAGS += -std=c++17 -O3 -Wno-unused-result -g
|
||||
LINK_FLAGS :=
|
||||
|
||||
all: transpose
|
||||
|
||||
debug: CXXFLAGS += -ggdb -g
|
||||
debug: transpose
|
||||
|
||||
transpose: transpose.cpp
|
||||
hipcc ${CXXFLAGS} -o $@ $^
|
||||
hipcc ${CXXFLAGS} -o $@ $^ ${LINK_FLAGS}
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
CXXFLAGS += -std=c++@CMAKE_CXX_STANDARD@ @transpose_CXX_FLAGS@
|
||||
LINKFLAGS := @transpose_LINK_FLAGS@
|
||||
|
||||
all: transpose
|
||||
|
||||
debug: CXXFLAGS += -ggdb -g
|
||||
debug: transpose
|
||||
|
||||
transpose: transpose.cpp
|
||||
hipcc ${CXXFLAGS} -o $@ $^
|
||||
hipcc ${CXXFLAGS} -o $@ $^ ${LINKFLAGS}
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
@@ -148,9 +148,19 @@ run(int argc, char** argv)
|
||||
free(out_matrix);
|
||||
}
|
||||
|
||||
#if defined(USE_MPI)
|
||||
# include <mpi.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
#if defined(USE_MPI)
|
||||
MPI_Init(&argc, &argv);
|
||||
#endif
|
||||
run(argc, argv);
|
||||
#if defined(USE_MPI)
|
||||
MPI_Finalize();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
Submodule projects/rocprofiler-systems/external/perfetto added at dd1f2f378f
+1
Submodule projects/rocprofiler-systems/external/timemory added at 7542f48e65
@@ -1,65 +0,0 @@
|
||||
# requires clang-tidy version 6.0+
|
||||
---
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
||||
AlwaysBreakAfterReturnType: TopLevel
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BasedOnStyle: Mozilla
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: false
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: true
|
||||
ColumnLimit: 90
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 0
|
||||
ContinuationIndentWidth: 4
|
||||
FixNamespaceComments: true
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
PointerAlignment: Left
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
...
|
||||
@@ -1,221 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/api/macros.hpp"
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/mpl/concepts.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
//
|
||||
// General APIs
|
||||
//
|
||||
TIMEMORY_DEFINE_NS_API(project, none) // dummy type
|
||||
TIMEMORY_DEFINE_NS_API(project, timemory) // provided by timemory API exclusively
|
||||
TIMEMORY_DEFINE_NS_API(project, python) // provided by timemory python interface
|
||||
TIMEMORY_DEFINE_NS_API(project, kokkosp) // kokkos profiling API
|
||||
//
|
||||
// Device APIs
|
||||
//
|
||||
TIMEMORY_DECLARE_NS_API(device, cpu) // collects data on CPU
|
||||
TIMEMORY_DECLARE_NS_API(device, gpu) // collects data on GPU
|
||||
//
|
||||
// Category APIs
|
||||
//
|
||||
TIMEMORY_DEFINE_NS_API(category, debugger) // provided debugging utilities
|
||||
TIMEMORY_DEFINE_NS_API(category, decorator) // decorates external profiler
|
||||
TIMEMORY_DEFINE_NS_API(category, external) // relies on external package
|
||||
TIMEMORY_DEFINE_NS_API(category, io) // collects I/O data
|
||||
TIMEMORY_DEFINE_NS_API(category, logger) // logs generic data or messages
|
||||
TIMEMORY_DEFINE_NS_API(category, hardware_counter) // collects HW counter data
|
||||
TIMEMORY_DEFINE_NS_API(category, memory) // collects memory data
|
||||
TIMEMORY_DEFINE_NS_API(category, resource_usage) // collects resource usage data
|
||||
TIMEMORY_DEFINE_NS_API(category, timing) // collects timing data
|
||||
TIMEMORY_DEFINE_NS_API(category, visualization) // related to viz (currently unused)
|
||||
//
|
||||
// External Third-party library APIs
|
||||
//
|
||||
TIMEMORY_DEFINE_NS_API(tpls, allinea)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, caliper)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, craypat)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, gotcha)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, gperftools)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, intel)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, likwid)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, nvidia)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, openmp)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, rocm)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, papi)
|
||||
TIMEMORY_DEFINE_NS_API(tpls, tau)
|
||||
//
|
||||
// OS-specific APIs
|
||||
//
|
||||
TIMEMORY_DEFINE_NS_API(os, agnostic)
|
||||
TIMEMORY_DEFINE_NS_API(os, supports_unix)
|
||||
TIMEMORY_DEFINE_NS_API(os, supports_linux)
|
||||
TIMEMORY_DEFINE_NS_API(os, supports_darwin)
|
||||
TIMEMORY_DEFINE_NS_API(os, supports_windows)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, project::timemory, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, project::python, true_type)
|
||||
//
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::debugger, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::decorator, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::external, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::io, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::logger, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::hardware_counter,
|
||||
true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::resource_usage,
|
||||
true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::timing, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, category::visualization,
|
||||
true_type)
|
||||
//
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::allinea, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::caliper, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::craypat, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::gotcha, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::gperftools, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::intel, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::likwid, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::nvidia, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::openmp, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::papi, true_type)
|
||||
TIMEMORY_DEFINE_CONCRETE_CONCEPT(is_runtime_configurable, tpls::tau, true_type)
|
||||
//
|
||||
namespace tim
|
||||
{
|
||||
namespace api
|
||||
{
|
||||
using native_tag = project::timemory;
|
||||
}
|
||||
//
|
||||
namespace trait
|
||||
{
|
||||
//
|
||||
#if !defined(TIMEMORY_UNIX)
|
||||
template <>
|
||||
struct is_available<os::supports_unix> : false_type
|
||||
{};
|
||||
#endif
|
||||
//
|
||||
#if !defined(TIMEMORY_LINUX)
|
||||
template <>
|
||||
struct is_available<os::supports_linux> : false_type
|
||||
{};
|
||||
#endif
|
||||
//
|
||||
#if !defined(TIMEMORY_MACOS)
|
||||
template <>
|
||||
struct is_available<os::supports_darwin> : false_type
|
||||
{};
|
||||
#endif
|
||||
//
|
||||
#if !defined(TIMEMORY_WINDOWS)
|
||||
template <>
|
||||
struct is_available<os::supports_windows> : false_type
|
||||
{};
|
||||
#endif
|
||||
//
|
||||
} // namespace trait
|
||||
//
|
||||
} // namespace tim
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
class JSONInputArchive;
|
||||
class XMLInputArchive;
|
||||
class XMLOutputArchive;
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// Default pre-processor settings
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
|
||||
#if !defined(TIMEMORY_DEFAULT_API)
|
||||
# define TIMEMORY_DEFAULT_API ::tim::project::timemory
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_API)
|
||||
# define TIMEMORY_API TIMEMORY_DEFAULT_API
|
||||
#endif
|
||||
|
||||
#if defined(DISABLE_TIMEMORY) || defined(TIMEMORY_DISABLED)
|
||||
# if !defined(TIMEMORY_DEFAULT_AVAILABLE)
|
||||
# define TIMEMORY_DEFAULT_AVAILABLE false_type
|
||||
# endif
|
||||
#else
|
||||
# if !defined(TIMEMORY_DEFAULT_AVAILABLE)
|
||||
# define TIMEMORY_DEFAULT_AVAILABLE true_type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DEFAULT_STATISTICS_TYPE)
|
||||
# if defined(TIMEMORY_USE_STATISTICS)
|
||||
# define TIMEMORY_DEFAULT_STATISTICS_TYPE true_type
|
||||
# else
|
||||
# define TIMEMORY_DEFAULT_STATISTICS_TYPE false_type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DEFAULT_PLOTTING)
|
||||
# define TIMEMORY_DEFAULT_PLOTTING false
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DEFAULT_ENABLED)
|
||||
# define TIMEMORY_DEFAULT_ENABLED true
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_PYTHON_PLOTTER)
|
||||
# define TIMEMORY_PYTHON_PLOTTER "python"
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DEFAULT_INPUT_ARCHIVE)
|
||||
# define TIMEMORY_DEFAULT_INPUT_ARCHIVE cereal::JSONInputArchive
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DEFAULT_OUTPUT_ARCHIVE)
|
||||
# define TIMEMORY_DEFAULT_OUTPUT_ARCHIVE ::tim::type_list<>
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_INPUT_ARCHIVE)
|
||||
# define TIMEMORY_INPUT_ARCHIVE TIMEMORY_DEFAULT_INPUT_ARCHIVE
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_OUTPUT_ARCHIVE)
|
||||
# define TIMEMORY_OUTPUT_ARCHIVE TIMEMORY_DEFAULT_OUTPUT_ARCHIVE
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/mpl/concepts.hpp"
|
||||
|
||||
/// \macro TIMEMORY_DECLARE_NS_API(NS, NAME)
|
||||
/// \brief Declare an API category. APIs are used to designate
|
||||
/// different project implementations, different external library tools, etc.
|
||||
///
|
||||
#if !defined(TIMEMORY_DECLARE_NS_API)
|
||||
# define TIMEMORY_DECLARE_NS_API(NS, NAME) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace NS \
|
||||
{ \
|
||||
struct NAME; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DECLARE_API)
|
||||
# define TIMEMORY_DECLARE_API(NAME) TIMEMORY_DECLARE_NS_API(api, NAME)
|
||||
#endif
|
||||
|
||||
//
|
||||
/// \macro TIMEMORY_DEFINE_NS_API(NS, NAME)
|
||||
/// \param NS sub-namespace within tim::
|
||||
/// \param NAME the name of the API
|
||||
///
|
||||
/// \brief Define an API category within a namespace
|
||||
///
|
||||
#if !defined(TIMEMORY_DEFINE_NS_API)
|
||||
# define TIMEMORY_DEFINE_NS_API(NS, NAME) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace NS \
|
||||
{ \
|
||||
struct NAME : public concepts::api \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
///
|
||||
/// \macro TIMEMORY_DEFINE_API
|
||||
/// \brief Define an API category. APIs are used to designate
|
||||
/// different project implementations, different external library tools, etc.
|
||||
/// Note: this macro inherits from \ref concepts::api instead of specializing
|
||||
/// is_api<...>, thus allowing specialization from tools downstream
|
||||
///
|
||||
#if !defined(TIMEMORY_DEFINE_API)
|
||||
# define TIMEMORY_DEFINE_API(NAME) TIMEMORY_DEFINE_NS_API(api, NAME)
|
||||
#endif
|
||||
@@ -1,110 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \file backends/process.hpp
|
||||
* \headerfile backends/process.hpp "timemory/backends/process.hpp"
|
||||
* Defines process backend functions
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
# include <sys/resource.h>
|
||||
# include <unistd.h>
|
||||
# if defined(TIMEMORY_MACOS)
|
||||
# include <libproc.h>
|
||||
# include <mach/mach.h>
|
||||
# endif
|
||||
#elif defined(TIMEMORY_WINDOWS)
|
||||
# if !defined(NOMINMAX)
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# if !defined(WIN32_LEAN_AND_MEAN)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace process
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
using id_t = pid_t;
|
||||
#elif defined(TIMEMORY_WINDOWS)
|
||||
using id_t = DWORD;
|
||||
#else
|
||||
using id_t = int;
|
||||
#endif
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \fn pid_t tim::process::get_id()
|
||||
/// \brief get the process id of this process
|
||||
///
|
||||
inline id_t
|
||||
get_id()
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
static auto instance = GetCurrentProcessId();
|
||||
#elif defined(TIMEMORY_UNIX)
|
||||
static auto instance = getpid();
|
||||
#else
|
||||
static auto instance = 0;
|
||||
#endif
|
||||
return instance;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \fn pid_t& tim::process::get_target_id()
|
||||
/// \brief get the target process id of this process (may differ from process::get_id)
|
||||
///
|
||||
inline id_t&
|
||||
get_target_id()
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
static auto instance = GetCurrentProcessId();
|
||||
#elif defined(TIMEMORY_UNIX)
|
||||
static auto instance = getpid();
|
||||
#else
|
||||
static auto instance = 0;
|
||||
#endif
|
||||
return instance;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace process
|
||||
} // namespace tim
|
||||
@@ -1,289 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define _TIM_STRINGIZE(X) _TIM_STRINGIZE2(X)
|
||||
#define _TIM_STRINGIZE2(X) #X
|
||||
#define _TIM_VAR_NAME_COMBINE(X, Y) X##Y
|
||||
#define _TIM_VARIABLE(Y) _TIM_VAR_NAME_COMBINE(timemory_variable_, Y)
|
||||
#define _TIM_SCOPE_DTOR(Y) _TIM_VAR_NAME_COMBINE(timemory_scoped_dtor_, Y)
|
||||
#define _TIM_TYPEDEF(Y) _TIM_VAR_NAME_COMBINE(timemory_typedef_, Y)
|
||||
#define _TIM_STORAGE_INIT(Y) _TIM_VAR_NAME_COMBINE(timemory_storage_initializer_, Y)
|
||||
|
||||
#define _TIM_LINESTR _TIM_STRINGIZE(__LINE__)
|
||||
|
||||
#if defined(TIMEMORY_PRETTY_FUNCTION) && !defined(_WINDOWS)
|
||||
# define _TIM_FUNC __PRETTY_FUNCTION__
|
||||
#elif defined(TIMEMORY_PRETTY_FUNCTION) && defined(_WINDOWS)
|
||||
# define _TIM_FUNC __FUNCSIG__
|
||||
#else
|
||||
# define _TIM_FUNC __FUNCTION__
|
||||
#endif
|
||||
|
||||
#if defined(DISABLE_TIMEMORY) || defined(TIMEMORY_DISABLED)
|
||||
# if !defined(TIMEMORY_SPRINTF)
|
||||
# define TIMEMORY_SPRINTF(...)
|
||||
# endif
|
||||
#else
|
||||
# if !defined(TIMEMORY_SPRINTF)
|
||||
# define TIMEMORY_SPRINTF(VAR, LEN, FMT, ...) \
|
||||
char VAR[LEN]; \
|
||||
snprintf(VAR, LEN, FMT, __VA_ARGS__);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_CODE)
|
||||
# if defined(DISABLE_TIMEMORY) || defined(TIMEMORY_DISABLED)
|
||||
# define TIMEMORY_CODE(...)
|
||||
# else
|
||||
# define TIMEMORY_CODE(...) __VA_ARGS__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Operating System
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64)
|
||||
# if !defined(_WINDOWS)
|
||||
# define _WINDOWS 1
|
||||
# endif
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
# if !defined(_MACOS)
|
||||
# define _MACOS 1
|
||||
# endif
|
||||
# if !defined(_UNIX)
|
||||
# define _UNIX 1
|
||||
# endif
|
||||
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
|
||||
# if !defined(_LINUX)
|
||||
# define _LINUX 1
|
||||
# endif
|
||||
# if !defined(_UNIX)
|
||||
# define _UNIX 1
|
||||
# endif
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix)
|
||||
# if !defined(_UNIX)
|
||||
# define _UNIX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64)
|
||||
# if !defined(TIMEMORY_WINDOWS)
|
||||
# define TIMEMORY_WINDOWS 1
|
||||
# endif
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
# if !defined(TIMEMORY_MACOS)
|
||||
# define TIMEMORY_MACOS 1
|
||||
# endif
|
||||
# if !defined(TIMEMORY_UNIX)
|
||||
# define TIMEMORY_UNIX 1
|
||||
# endif
|
||||
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
|
||||
# if !defined(TIMEMORY_LINUX)
|
||||
# define TIMEMORY_LINUX 1
|
||||
# endif
|
||||
# if !defined(TIMEMORY_UNIX)
|
||||
# define TIMEMORY_UNIX 1
|
||||
# endif
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix)
|
||||
# if !defined(TIMEMORY_UNIX)
|
||||
# define TIMEMORY_UNIX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// General attribute
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(TIMEMORY_ATTRIBUTE)
|
||||
# if !defined(_MSC_VER)
|
||||
# define TIMEMORY_ATTRIBUTE(attr) __attribute__((attr))
|
||||
# else
|
||||
# define TIMEMORY_ATTRIBUTE(attr) __declspec(attr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Windows DLL settings
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(TIMEMORY_CDLL)
|
||||
# if defined(_WINDOWS)
|
||||
# if defined(TIMEMORY_CDLL_EXPORT)
|
||||
# define TIMEMORY_CDLL __declspec(dllexport)
|
||||
# elif defined(TIMEMORY_CDLL_IMPORT)
|
||||
# define TIMEMORY_CDLL __declspec(dllimport)
|
||||
# else
|
||||
# define TIMEMORY_CDLL
|
||||
# endif
|
||||
# else
|
||||
# define TIMEMORY_CDLL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_DLL)
|
||||
# if defined(_WINDOWS)
|
||||
# if defined(TIMEMORY_DLL_EXPORT)
|
||||
# define TIMEMORY_DLL __declspec(dllexport)
|
||||
# elif defined(TIMEMORY_DLL_IMPORT)
|
||||
# define TIMEMORY_DLL __declspec(dllimport)
|
||||
# else
|
||||
# define TIMEMORY_DLL
|
||||
# endif
|
||||
# else
|
||||
# define TIMEMORY_DLL
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Visibility
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(TIMEMORY_VISIBILITY)
|
||||
# if !defined(_MSC_VER)
|
||||
# define TIMEMORY_VISIBILITY(mode) TIMEMORY_ATTRIBUTE(visibility(mode))
|
||||
# else
|
||||
# define TIMEMORY_VISIBILITY(mode)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_VISIBLE)
|
||||
# define TIMEMORY_VISIBLE TIMEMORY_VISIBILITY("default")
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_HIDDEN)
|
||||
# define TIMEMORY_HIDDEN TIMEMORY_VISIBILITY("hidden")
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Instrumentation
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(_WINDOWS)
|
||||
# if !defined(TIMEMORY_NEVER_INSTRUMENT)
|
||||
# if defined(__clang__)
|
||||
# define TIMEMORY_NEVER_INSTRUMENT \
|
||||
TIMEMORY_ATTRIBUTE(no_instrument_function) \
|
||||
TIMEMORY_ATTRIBUTE(xray_never_instrument)
|
||||
# else
|
||||
# define TIMEMORY_NEVER_INSTRUMENT TIMEMORY_ATTRIBUTE(no_instrument_function)
|
||||
# endif
|
||||
# endif
|
||||
//
|
||||
# if !defined(TIMEMORY_INSTRUMENT)
|
||||
# define TIMEMORY_INSTRUMENT TIMEMORY_ATTRIBUTE(xray_always_instrument)
|
||||
# endif
|
||||
#else
|
||||
# if !defined(TIMEMORY_NEVER_INSTRUMENT)
|
||||
# define TIMEMORY_NEVER_INSTRUMENT
|
||||
# endif
|
||||
//
|
||||
# if !defined(TIMEMORY_INSTRUMENT)
|
||||
# define TIMEMORY_INSTRUMENT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Symbol override
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(TIMEMORY_WEAK_PREFIX)
|
||||
# if !defined(_MSC_VER)
|
||||
# if defined(__clang__) && defined(__APPLE__)
|
||||
# define TIMEMORY_WEAK_PREFIX
|
||||
# else
|
||||
# define TIMEMORY_WEAK_PREFIX TIMEMORY_ATTRIBUTE(weak)
|
||||
# endif
|
||||
# else
|
||||
# define TIMEMORY_WEAK_PREFIX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_WEAK_POSTFIX)
|
||||
# if !defined(_MSC_VER)
|
||||
# if defined(__clang__) && defined(__APPLE__)
|
||||
# define TIMEMORY_WEAK_POSTFIX TIMEMORY_ATTRIBUTE(weak_import)
|
||||
# else
|
||||
# define TIMEMORY_WEAK_POSTFIX
|
||||
# endif
|
||||
# else
|
||||
# define TIMEMORY_WEAK_POSTFIX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Library Constructor/Destructor
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(TIMEMORY_CTOR)
|
||||
# if !defined(_WINDOWS)
|
||||
# define TIMEMORY_CTOR TIMEMORY_ATTRIBUTE(constructor)
|
||||
# else
|
||||
# define TIMEMORY_CTOR
|
||||
# endif
|
||||
#endif
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#if !defined(TIMEMORY_DTOR)
|
||||
# if !defined(_WINDOWS)
|
||||
# define TIMEMORY_DTOR TIMEMORY_ATTRIBUTE(destructor)
|
||||
# else
|
||||
# define TIMEMORY_DTOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// WINDOWS WARNINGS (apply to C code)
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// MSVC compiler
|
||||
#if defined(_MSC_VER) && _MSC_VER > 0 && !defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_MSVC_COMPILER
|
||||
#endif
|
||||
|
||||
#if defined(TIMEMORY_MSVC_COMPILER) && !defined(TIMEMORY_MSVC_WARNINGS)
|
||||
|
||||
# pragma warning(disable : 4996) // function may be unsafe
|
||||
# pragma warning(disable : 5105) // macro produce 'defined' has undefined behavior
|
||||
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/environment/declaration.hpp"
|
||||
#include "timemory/environment/macros.hpp"
|
||||
#include "timemory/environment/types.hpp"
|
||||
|
||||
#if !defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
|
||||
# include "timemory/environment/definition.hpp"
|
||||
#endif
|
||||
@@ -1,268 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/environment/macros.hpp"
|
||||
#include "timemory/environment/types.hpp"
|
||||
#include "timemory/macros/compiler.hpp"
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/tpls/cereal/cereal.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
#include "timemory/utility/utility.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// environment
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
class env_settings
|
||||
{
|
||||
public:
|
||||
using string_t = std::string;
|
||||
using env_map_t = std::map<string_t, string_t>;
|
||||
using env_uomap_t = std::map<string_t, string_t>;
|
||||
using env_pair_t = std::pair<string_t, string_t>;
|
||||
using iterator = typename env_map_t::iterator;
|
||||
using const_iterator = typename env_map_t::const_iterator;
|
||||
|
||||
public:
|
||||
static env_settings* instance();
|
||||
|
||||
private:
|
||||
// if passed a global, insert m_env into it's array
|
||||
env_settings(env_settings* _global = nullptr, int _id = 0);
|
||||
|
||||
// only the zero id deletes
|
||||
~env_settings();
|
||||
|
||||
public:
|
||||
template <typename Tp>
|
||||
void insert(const std::string& env_id, Tp val);
|
||||
|
||||
env_map_t get() const;
|
||||
iterator get(const string_t& _entry) { return m_env->find(_entry); }
|
||||
const_iterator get(const string_t& _entry) const { return m_env->find(_entry); }
|
||||
iterator begin() { return m_env->begin(); }
|
||||
iterator end() { return m_env->end(); }
|
||||
const_iterator begin() const { return m_env->begin(); }
|
||||
const_iterator end() const { return m_env->end(); }
|
||||
|
||||
void print(std::ostream&) const;
|
||||
friend std::ostream& operator<<(std::ostream& os, const env_settings& env)
|
||||
{
|
||||
env.print(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// serialization
|
||||
//
|
||||
template <typename Archive>
|
||||
void serialize(Archive& ar, unsigned int);
|
||||
|
||||
template <typename Archive>
|
||||
static void serialize_environment(Archive& ar)
|
||||
{
|
||||
if(instance())
|
||||
instance()->serialize(ar, TIMEMORY_GET_CLASS_VERSION(tim::env_settings));
|
||||
}
|
||||
|
||||
private:
|
||||
static std::atomic_bool& lock_flag()
|
||||
{
|
||||
static std::atomic_bool _instance(false);
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void collapse();
|
||||
|
||||
private:
|
||||
int m_id = 0;
|
||||
env_uomap_t* m_env = new env_uomap_t{};
|
||||
std::vector<env_uomap_t*> m_env_other;
|
||||
};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
void
|
||||
env_settings::insert(const std::string& env_id, Tp val)
|
||||
{
|
||||
#if !defined(TIMEMORY_DISABLE_STORE_ENVIRONMENT)
|
||||
std::stringstream ss;
|
||||
ss << std::boolalpha << val;
|
||||
|
||||
auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
|
||||
if(lock_flag().load() && !lk.owns_lock())
|
||||
lk.lock();
|
||||
|
||||
if(m_env &&
|
||||
(m_env->find(env_id) == m_env->end() || m_env->find(env_id)->second != ss.str()))
|
||||
(*m_env)[env_id] = ss.str();
|
||||
#else
|
||||
consume_parameters(env_id, val);
|
||||
#endif
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Archive>
|
||||
void
|
||||
env_settings::serialize(Archive& ar, const unsigned int)
|
||||
{
|
||||
auto _tmp = env_uomap_t{};
|
||||
if(!m_env)
|
||||
m_env = &_tmp;
|
||||
|
||||
collapse();
|
||||
|
||||
auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
|
||||
lock_flag().store(true);
|
||||
|
||||
if(!lk.owns_lock())
|
||||
lk.lock();
|
||||
|
||||
ar(cereal::make_nvp("environment", *m_env));
|
||||
|
||||
if(m_env == &_tmp)
|
||||
m_env = nullptr;
|
||||
|
||||
lock_flag().store(false);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp
|
||||
get_env(const std::string& env_id, Tp _default, bool _store)
|
||||
{
|
||||
if(env_id.empty())
|
||||
return _default;
|
||||
|
||||
auto* _env_settings = env_settings::instance();
|
||||
char* env_var = std::getenv(env_id.c_str());
|
||||
if(env_var)
|
||||
{
|
||||
std::string str_var = std::string(env_var);
|
||||
std::stringstream iss{ str_var };
|
||||
auto var = Tp{};
|
||||
iss >> var;
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert<Tp>(env_id, var);
|
||||
return var;
|
||||
}
|
||||
// record default value
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert<Tp>(env_id, _default);
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp
|
||||
get_env_choice(const std::string& env_id, Tp _default, std::set<Tp> _choices)
|
||||
{
|
||||
assert(!_choices.empty());
|
||||
auto _choice = get_env<Tp>(env_id, _default);
|
||||
|
||||
// check that the choice is valid
|
||||
if(_choices.find(_choice) == _choices.end())
|
||||
{
|
||||
std::ostringstream _msg{};
|
||||
_msg << "Error! Invalid value \"" << _choice << "\" for " << env_id
|
||||
<< ". Valid choices are: ";
|
||||
std::ostringstream _opts{};
|
||||
for(const auto& itr : _choices)
|
||||
_opts << ", \"" << itr << "\"";
|
||||
_msg << _opts.str().substr(2);
|
||||
throw std::runtime_error(_msg.str());
|
||||
}
|
||||
|
||||
return _choice;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp
|
||||
load_env(const std::string& env_id, Tp _default)
|
||||
{
|
||||
if(env_id.empty())
|
||||
return _default;
|
||||
|
||||
auto* _env_settings = env_settings::instance();
|
||||
if(!_env_settings)
|
||||
return _default;
|
||||
|
||||
auto itr = _env_settings->get(env_id);
|
||||
if(itr != _env_settings->end())
|
||||
{
|
||||
std::stringstream iss{ itr->second };
|
||||
auto var = Tp{};
|
||||
iss >> var;
|
||||
return var;
|
||||
}
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
void
|
||||
set_env(const std::string& env_var, const Tp& _val, int override)
|
||||
{
|
||||
std::stringstream ss_val;
|
||||
ss_val << _val;
|
||||
#if defined(TIMEMORY_MACOS) || (defined(TIMEMORY_LINUX) && (_POSIX_C_SOURCE >= 200112L))
|
||||
setenv(env_var.c_str(), ss_val.str().c_str(), override);
|
||||
#elif defined(TIMEMORY_WINDOWS)
|
||||
auto _curr = get_env<std::string>(env_var, "");
|
||||
if(_curr.empty() || override > 0)
|
||||
_putenv_s(env_var.c_str(), ss_val.str().c_str());
|
||||
#else
|
||||
consume_parameters(env_var, _val, override, ss_val);
|
||||
#endif
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace tim
|
||||
@@ -1,362 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/**
|
||||
* \file timemory/environment/definition.hpp
|
||||
* \brief The definitions for the types in environment
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/environment/declaration.hpp"
|
||||
#include "timemory/environment/macros.hpp"
|
||||
#include "timemory/environment/types.hpp"
|
||||
#include "timemory/utility/transient_function.hpp"
|
||||
#include "timemory/utility/utility.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <iosfwd>
|
||||
#include <mutex>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace regex_const = std::regex_constants;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#if !defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// environment
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// if passed a global, insert m_env into it's array
|
||||
//
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(env_settings::env_settings)
|
||||
(env_settings* _global, int _id)
|
||||
: m_id(_id)
|
||||
, m_env(new env_uomap_t)
|
||||
{
|
||||
if(_global && _id != 0)
|
||||
{
|
||||
auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
|
||||
lock_flag().store(true);
|
||||
if(!lk.owns_lock())
|
||||
lk.lock();
|
||||
_global->m_env_other.emplace_back(m_env);
|
||||
lock_flag().store(false);
|
||||
}
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// only the zero id deletes
|
||||
//
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(env_settings::~env_settings())
|
||||
{
|
||||
if(m_id == 0)
|
||||
{
|
||||
delete m_env;
|
||||
for(auto& itr : m_env_other)
|
||||
delete itr;
|
||||
}
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(env_settings::env_map_t)
|
||||
env_settings::get() const
|
||||
{
|
||||
auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
|
||||
lock_flag().store(true);
|
||||
if(!lk.owns_lock())
|
||||
lk.lock();
|
||||
|
||||
auto _tmp = *m_env;
|
||||
env_map_t _ret;
|
||||
for(const auto& itr : _tmp)
|
||||
_ret[itr.first] = itr.second;
|
||||
|
||||
lock_flag().store(false);
|
||||
return _ret;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(void)
|
||||
env_settings::print(std::ostream& os) const
|
||||
{
|
||||
if(m_id == 0)
|
||||
const_cast<env_settings&>(*this).collapse();
|
||||
|
||||
auto _data = get();
|
||||
|
||||
size_t _w = 35;
|
||||
for(const auto& itr : _data)
|
||||
_w = std::max<size_t>(itr.first.length(), _w);
|
||||
|
||||
std::stringstream filler;
|
||||
filler.fill('-');
|
||||
filler << '#';
|
||||
filler << std::setw(88) << "";
|
||||
filler << '#';
|
||||
|
||||
std::stringstream ss;
|
||||
ss << filler.str() << '\n';
|
||||
ss << "# Environment settings:\n";
|
||||
for(const auto& itr : _data)
|
||||
{
|
||||
ss << "# " << std::setw(_w) << std::right << itr.first << "\t = \t" << std::left
|
||||
<< itr.second << '\n';
|
||||
}
|
||||
ss << filler.str();
|
||||
os << ss.str() << '\n';
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// NOLINTNEXTLINE
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(void)
|
||||
env_settings::collapse()
|
||||
{
|
||||
if(m_id != 0)
|
||||
return;
|
||||
|
||||
auto_lock_t lk(type_mutex<env_settings>(), std::defer_lock);
|
||||
if(!lk.owns_lock())
|
||||
lk.lock();
|
||||
|
||||
lock_flag().store(true);
|
||||
|
||||
// insert all the other maps into this map
|
||||
for(size_t i = 0; i < m_env_other.size(); ++i)
|
||||
{
|
||||
// get the map instance
|
||||
auto* itr = m_env_other[i];
|
||||
if(itr)
|
||||
{
|
||||
// loop over entries
|
||||
for(const auto& mitr : *m_env_other[i])
|
||||
{
|
||||
auto key = mitr.first;
|
||||
if(m_env->find(key) != m_env->end())
|
||||
{
|
||||
// if the key already exists and if the entries differ,
|
||||
// create a new unique entry for the index
|
||||
if(m_env->find(key)->second != mitr.second)
|
||||
{
|
||||
key += string_t("[@") + std::to_string(i + 1) + string_t("]");
|
||||
(*m_env)[key] = mitr.second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if a new entry, insert without unique tag to avoid duplication
|
||||
// when thread count is very high
|
||||
(*m_env)[key] = mitr.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lock_flag().store(false);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// specialization for string since the above will have issues if string includes spaces
|
||||
//
|
||||
template <>
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(std::string)
|
||||
get_env(const std::string& env_id, std::string _default, bool _store)
|
||||
{
|
||||
if(env_id.empty())
|
||||
return _default;
|
||||
|
||||
auto* _env_settings = env_settings::instance();
|
||||
char* env_var = std::getenv(env_id.c_str());
|
||||
if(env_var)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << env_var;
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert(env_id, ss.str());
|
||||
return ss.str();
|
||||
}
|
||||
// record default value
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert(env_id, _default);
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// overload for boolean
|
||||
//
|
||||
template <>
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(bool)
|
||||
get_env(const std::string& env_id, bool _default, bool _store)
|
||||
{
|
||||
if(env_id.empty())
|
||||
return _default;
|
||||
|
||||
auto* _env_settings = env_settings::instance();
|
||||
char* env_var = std::getenv(env_id.c_str());
|
||||
if(env_var)
|
||||
{
|
||||
std::string var = std::string(env_var);
|
||||
bool val = true;
|
||||
if(var.find_first_not_of("0123456789") == std::string::npos)
|
||||
{
|
||||
val = (bool) atoi(var.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto& itr : var)
|
||||
itr = tolower(itr);
|
||||
for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
|
||||
{
|
||||
if(var == itr)
|
||||
{
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert<bool>(env_id, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert<bool>(env_id, val);
|
||||
return val;
|
||||
}
|
||||
// record default value
|
||||
if(_env_settings && _store)
|
||||
_env_settings->insert<bool>(env_id, _default);
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// specialization for string since the above will have issues if string includes spaces
|
||||
//
|
||||
template <>
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(std::string)
|
||||
load_env(const std::string& env_id, std::string _default)
|
||||
{
|
||||
if(env_id.empty())
|
||||
return _default;
|
||||
|
||||
auto* _env_settings = env_settings::instance();
|
||||
auto itr = _env_settings->get(env_id);
|
||||
if(itr != _env_settings->end())
|
||||
return itr->second;
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// overload for boolean
|
||||
//
|
||||
template <>
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(bool)
|
||||
load_env(const std::string& env_id, bool _default)
|
||||
{
|
||||
if(env_id.empty())
|
||||
return _default;
|
||||
|
||||
auto* _env_settings = env_settings::instance();
|
||||
auto itr = _env_settings->get(env_id);
|
||||
if(itr != _env_settings->end())
|
||||
{
|
||||
auto val = itr->second;
|
||||
const auto regex_constants = regex_const::egrep | regex_const::icase;
|
||||
const std::string pattern = "^(off|false|no|n|f|0)$";
|
||||
bool _match = false;
|
||||
try
|
||||
{
|
||||
_match = std::regex_match(val, std::regex(pattern, regex_constants));
|
||||
} catch(std::bad_cast&)
|
||||
{
|
||||
for(auto& vitr : val)
|
||||
vitr = tolower(vitr);
|
||||
for(const auto& vitr : { "off", "false", "no", "n", "f", "0" })
|
||||
{
|
||||
if(val == vitr)
|
||||
{
|
||||
_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (_match) ? false : true;
|
||||
}
|
||||
|
||||
// return default if not specified in environment
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(void)
|
||||
print_env(std::ostream& os) { os << (*env_settings::instance()); }
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_ENVIRONMENT_LINKAGE(tim::env_settings*)
|
||||
env_settings::instance()
|
||||
{
|
||||
static std::atomic<int> _count{ 0 };
|
||||
static env_settings _instance{};
|
||||
static thread_local int _id = _count++;
|
||||
static thread_local env_settings* _local =
|
||||
(_id == 0) ? (&_instance) : new env_settings{ &_instance, _id };
|
||||
static thread_local auto _ldtor = scope::destructor{ []() {
|
||||
if(_local == &_instance || _id == 0)
|
||||
return;
|
||||
delete _local;
|
||||
_local = nullptr;
|
||||
} };
|
||||
return _local;
|
||||
(void) _ldtor;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#endif // !defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace tim
|
||||
@@ -1,69 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/utility/macros.hpp"
|
||||
|
||||
#if defined(TIMEMORY_CORE_SOURCE)
|
||||
# define TIMEMORY_ENVIRONMENT_SOURCE
|
||||
#elif defined(TIMEMORY_USE_CORE_EXTERN)
|
||||
# define TIMEMORY_USE_ENVIRONMENT_EXTERN
|
||||
#endif
|
||||
//
|
||||
#if defined(TIMEMORY_USE_EXTERN) && !defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
|
||||
# define TIMEMORY_USE_ENVIRONMENT_EXTERN
|
||||
#endif
|
||||
|
||||
#if defined(TIMEMORY_ENVIRONMENT_SOURCE)
|
||||
# define TIMEMORY_ENVIRONMENT_LINKAGE(...) __VA_ARGS__
|
||||
#elif defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
|
||||
# define TIMEMORY_ENVIRONMENT_LINKAGE(...) extern __VA_ARGS__
|
||||
#else
|
||||
# define TIMEMORY_ENVIRONMENT_LINKAGE(...) inline __VA_ARGS__
|
||||
#endif
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#if !defined(TIMEMORY_ENVIRONMENT_EXTERN_TEMPLATE)
|
||||
# if defined(TIMEMORY_ENVIRONMENT_SOURCE)
|
||||
# define TIMEMORY_ENVIRONMENT_EXTERN_TEMPLATE(TYPE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
template TYPE get_env<TYPE>(const std::string&, TYPE); \
|
||||
template void set_env<TYPE>(const std::string&, const TYPE&, int); \
|
||||
}
|
||||
# elif defined(TIMEMORY_USE_ENVIRONMENT_EXTERN)
|
||||
# define TIMEMORY_ENVIRONMENT_EXTERN_TEMPLATE(TYPE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
extern template TYPE get_env<TYPE>(const std::string&, TYPE); \
|
||||
extern template void set_env<TYPE>(const std::string&, const TYPE&, int); \
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
# define TIMEMORY_ENVIRONMENT_EXTERN_TEMPLATE(...)
|
||||
#endif
|
||||
//
|
||||
//======================================================================================//
|
||||
@@ -1,103 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/environment/macros.hpp"
|
||||
#include "timemory/utility/types.hpp"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// environment
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
class env_settings;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp
|
||||
get_env(const std::string& env_id, Tp _default = Tp{}, bool _store = true);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <>
|
||||
std::string
|
||||
get_env(const std::string& env_id, std::string _default, bool _store);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <>
|
||||
bool
|
||||
get_env(const std::string& env_id, bool _default, bool _store);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp
|
||||
get_env_choice(const std::string& env_id, Tp _default, std::set<Tp> _choices);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
Tp
|
||||
load_env(const std::string& env_id, Tp _default = Tp{});
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <>
|
||||
std::string
|
||||
load_env(const std::string& env_id, std::string _default);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <>
|
||||
bool
|
||||
load_env(const std::string& env_id, bool _default);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
void
|
||||
print_env(std::ostream& os = std::cout);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp>
|
||||
void
|
||||
set_env(const std::string& env_var, const Tp& _val, int override = 0);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace tim
|
||||
|
||||
TIMEMORY_SET_CLASS_VERSION(0, tim::env_settings)
|
||||
@@ -1,366 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/general/types.hpp"
|
||||
#include "timemory/hash/declaration.hpp"
|
||||
#include "timemory/mpl/apply.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace impl
|
||||
{
|
||||
template <typename... Tp>
|
||||
struct source_location_constant_char;
|
||||
|
||||
template <>
|
||||
struct source_location_constant_char<>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct source_location_constant_char<const char*>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
struct source_location_constant_char<Tp>
|
||||
{
|
||||
static constexpr bool value = std::is_same<Tp, const char*>::value;
|
||||
};
|
||||
|
||||
template <typename Tp, typename Up, typename... Tail>
|
||||
struct source_location_constant_char<Tp, Up, Tail...>
|
||||
{
|
||||
static constexpr bool value = source_location_constant_char<Tp>::value &&
|
||||
source_location_constant_char<Up>::value &&
|
||||
source_location_constant_char<Tail...>::value;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
/// \class tim::source_location
|
||||
/// \brief Provides source location information and variadic joining of source location
|
||||
/// tags
|
||||
class source_location
|
||||
{
|
||||
public:
|
||||
using join_type = mpl::apply<std::string>;
|
||||
using result_type = std::tuple<std::string, size_t>;
|
||||
|
||||
private:
|
||||
template <typename... Tp>
|
||||
static constexpr bool is_constant_char()
|
||||
{
|
||||
return impl::source_location_constant_char<decay_t<Tp>...>::value;
|
||||
}
|
||||
|
||||
public:
|
||||
//
|
||||
// Public types
|
||||
//
|
||||
|
||||
//==================================================================================//
|
||||
//
|
||||
enum class mode : short
|
||||
{
|
||||
blank = 0,
|
||||
basic = 1,
|
||||
full = 2,
|
||||
complete = 3
|
||||
};
|
||||
|
||||
//==================================================================================//
|
||||
//
|
||||
struct captured
|
||||
{
|
||||
public:
|
||||
const result_type& get() const { return m_result; }
|
||||
const std::string& get_id() const { return std::get<0>(m_result); }
|
||||
const hash_value_t& get_hash() const { return std::get<1>(m_result); }
|
||||
|
||||
explicit captured(result_type _result)
|
||||
: m_result(std::move(_result))
|
||||
{}
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(captured)
|
||||
|
||||
private:
|
||||
friend class source_location;
|
||||
result_type m_result = result_type("", 0);
|
||||
|
||||
template <typename... ArgsT, enable_if_t<(sizeof...(ArgsT) > 0), int> = 0>
|
||||
captured& set(const source_location& obj, ArgsT&&... _args)
|
||||
{
|
||||
switch(obj.m_mode)
|
||||
{
|
||||
case mode::blank:
|
||||
{
|
||||
auto&& _tmp = join_type::join("", std::forward<ArgsT>(_args)...);
|
||||
m_result = result_type(_tmp, add_hash_id(_tmp));
|
||||
break;
|
||||
}
|
||||
case mode::basic:
|
||||
case mode::full:
|
||||
case mode::complete:
|
||||
{
|
||||
auto&& _suffix = join_type::join("", std::forward<ArgsT>(_args)...);
|
||||
if(_suffix.empty())
|
||||
{
|
||||
m_result = result_type(obj.m_prefix, add_hash_id(obj.m_prefix));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto _tmp = join_type::join('/', obj.m_prefix.c_str(), _suffix);
|
||||
m_result = result_type(_tmp, add_hash_id(_tmp));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... ArgsT, enable_if_t<sizeof...(ArgsT) == 0, int> = 0>
|
||||
captured& set(const source_location& obj, ArgsT&&... _args)
|
||||
{
|
||||
tim::consume_parameters(std::forward<ArgsT>(_args)...);
|
||||
m_result = result_type(obj.m_prefix, add_hash_id(obj.m_prefix));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
//
|
||||
// Static functions
|
||||
//
|
||||
|
||||
//==================================================================================//
|
||||
//
|
||||
template <typename... ArgsT>
|
||||
static captured get_captured_inline(const mode& _mode, const char* _func, int _line,
|
||||
const char* _fname, ArgsT&&... _args)
|
||||
{
|
||||
source_location _loc{ _mode, _func, _line, _fname,
|
||||
std::forward<ArgsT>(_args)... };
|
||||
return _loc.get_captured(std::forward<ArgsT>(_args)...);
|
||||
}
|
||||
|
||||
public:
|
||||
//
|
||||
// Constructors, destructors, etc.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename... ArgsT, enable_if_t<!is_constant_char<ArgsT...>(), int> = 0>
|
||||
source_location(const mode& _mode, const char* _func, int _line, const char* _fname,
|
||||
ArgsT&&...)
|
||||
: m_mode(_mode)
|
||||
{
|
||||
switch(m_mode)
|
||||
{
|
||||
case mode::blank: break;
|
||||
case mode::basic: compute_data(_func); break;
|
||||
case mode::complete:
|
||||
case mode::full:
|
||||
compute_data(_func, _line, _fname, m_mode == mode::full);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// if a const char* is passed, assume it is constant
|
||||
//
|
||||
template <typename... ArgsT, enable_if_t<is_constant_char<ArgsT...>(), int> = 0>
|
||||
source_location(const mode& _mode, const char* _func, int _line, const char* _fname,
|
||||
ArgsT&&... _args)
|
||||
: m_mode(_mode)
|
||||
{
|
||||
auto _arg = join_type::join("", _args...);
|
||||
switch(m_mode)
|
||||
{
|
||||
case mode::blank:
|
||||
{
|
||||
// label and hash
|
||||
auto&& _label = _arg;
|
||||
auto&& _hash = add_hash_id(_label);
|
||||
m_captured = captured(result_type{ _label, _hash });
|
||||
break;
|
||||
}
|
||||
case mode::basic:
|
||||
{
|
||||
compute_data(_func);
|
||||
auto&& _label = _join(_arg.c_str());
|
||||
auto&& _hash = add_hash_id(_label);
|
||||
m_captured = captured(result_type{ _label, _hash });
|
||||
break;
|
||||
}
|
||||
case mode::full:
|
||||
case mode::complete:
|
||||
{
|
||||
compute_data(_func, _line, _fname, m_mode == mode::full);
|
||||
// label and hash
|
||||
auto&& _label = _join(_arg.c_str());
|
||||
auto&& _hash = add_hash_id(_label);
|
||||
m_captured = captured(result_type{ _label, _hash });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
source_location() = delete;
|
||||
~source_location() = default;
|
||||
source_location(const source_location&) = delete;
|
||||
source_location(source_location&&) = default;
|
||||
source_location& operator=(const source_location&) = delete;
|
||||
source_location& operator=(source_location&&) = default;
|
||||
|
||||
protected:
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
void compute_data(const char* _func) { m_prefix = _func; }
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
void compute_data(const char* _func, int _line, const char* _fname, bool shorten)
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
static const char delim = '\\';
|
||||
#else
|
||||
static const char delim = '/';
|
||||
#endif
|
||||
std::string _filename(_fname);
|
||||
if(shorten)
|
||||
{
|
||||
if(_filename.find(delim) != std::string::npos)
|
||||
_filename = _filename.substr(_filename.find_last_of(delim) + 1);
|
||||
}
|
||||
|
||||
if(_line < 0)
|
||||
{
|
||||
if(_filename.length() > 0)
|
||||
{
|
||||
m_prefix = join_type::join("", _func, '@', _filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefix = _func;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_filename.length() > 0)
|
||||
{
|
||||
m_prefix = join_type::join("", _func, '@', _filename, ':', _line);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefix = join_type::join("", _func, ':', _line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
template <
|
||||
typename... ArgsT,
|
||||
enable_if_t<(sizeof...(ArgsT) > 0) && !is_constant_char<ArgsT...>(), int> = 0>
|
||||
const captured& get_captured(ArgsT&&... _args)
|
||||
{
|
||||
return m_captured.set(*this, std::forward<ArgsT>(_args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
const captured& get_captured() const { return m_captured; }
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
template <
|
||||
typename... ArgsT,
|
||||
enable_if_t<(sizeof...(ArgsT) > 0) && is_constant_char<ArgsT...>(), int> = 0>
|
||||
const captured& get_captured(ArgsT&&...)
|
||||
{
|
||||
return m_captured;
|
||||
}
|
||||
|
||||
private:
|
||||
mode m_mode;
|
||||
std::string m_prefix = {};
|
||||
captured m_captured;
|
||||
|
||||
private:
|
||||
std::string _join(const char* _arg)
|
||||
{
|
||||
return (strcmp(_arg, "") == 0) ? m_prefix
|
||||
: join_type::join('/', m_prefix.c_str(), _arg);
|
||||
}
|
||||
};
|
||||
//
|
||||
namespace internal
|
||||
{
|
||||
namespace
|
||||
{
|
||||
// anonymous namespace to make sure the static instance is local to each .cpp
|
||||
// making it static also helps ensure this
|
||||
template <size_t, size_t, typename... Args>
|
||||
static inline auto&
|
||||
get_static_source_location(Args&&... args)
|
||||
{
|
||||
static source_location _instance{ std::forward<Args>(args)... };
|
||||
consume_parameters(std::forward<Args>(args)...);
|
||||
return _instance;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace internal
|
||||
//
|
||||
// static function should be local to each .cpp
|
||||
//
|
||||
// LineN should be '__LINE__': this ensures that each use in a source file is unique
|
||||
// CountN should be '__COUNTER__': this ensures that each source file has unique integer
|
||||
template <size_t LineN, size_t CountN, typename... Args>
|
||||
static inline auto&
|
||||
get_static_source_location(Args&&... args)
|
||||
{
|
||||
return internal::get_static_source_location<LineN, CountN>(
|
||||
std::forward<Args>(args)...);
|
||||
consume_parameters(std::forward<Args>(args)...);
|
||||
}
|
||||
//
|
||||
} // namespace tim
|
||||
@@ -1,68 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \headerfile "timemory/general/types.hpp"
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
class source_location;
|
||||
//
|
||||
template <size_t, size_t, typename... Args>
|
||||
static inline auto&
|
||||
get_static_source_location(Args&&... args);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace tim
|
||||
|
||||
#if !defined(TIMEMORY_SOURCE_LOCATION)
|
||||
|
||||
# define _AUTO_LOCATION_COMBINE(X, Y) X##Y
|
||||
# define _AUTO_LOCATION(Y) _AUTO_LOCATION_COMBINE(timemory_source_location_, Y)
|
||||
|
||||
# define TIMEMORY_SOURCE_LOCATION(MODE, ...) \
|
||||
::tim::source_location(MODE, __FUNCTION__, __LINE__, __FILE__, __VA_ARGS__)
|
||||
|
||||
# define TIMEMORY_CAPTURE_MODE(MODE_TYPE) ::tim::source_location::mode::MODE_TYPE
|
||||
|
||||
# define TIMEMORY_CAPTURE_ARGS(...) _AUTO_LOCATION(__LINE__).get_captured(__VA_ARGS__)
|
||||
|
||||
# define TIMEMORY_INLINE_SOURCE_LOCATION(MODE, ...) \
|
||||
::tim::get_static_source_location<__LINE__, __COUNTER__>( \
|
||||
TIMEMORY_CAPTURE_MODE(MODE), __FUNCTION__, __LINE__, __FILE__, __VA_ARGS__) \
|
||||
.get_captured(__VA_ARGS__)
|
||||
|
||||
# define _TIM_STATIC_SRC_LOCATION(MODE, ...) \
|
||||
static thread_local auto _AUTO_LOCATION(__LINE__) = \
|
||||
TIMEMORY_SOURCE_LOCATION(TIMEMORY_CAPTURE_MODE(MODE), __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
@@ -1,85 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/hash/macros.hpp"
|
||||
#include "timemory/hash/types.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag, typename PtrT, typename PairT>
|
||||
PairT&
|
||||
get_shared_ptr_pair()
|
||||
{
|
||||
static auto _master = std::make_shared<Tp>();
|
||||
static std::atomic<int64_t> _count{ 0 };
|
||||
static thread_local auto _inst =
|
||||
PairT{ _master, PtrT{ (_count++ == 0) ? nullptr : new Tp{} } };
|
||||
return _inst;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag, typename PtrT, typename PairT>
|
||||
PtrT
|
||||
get_shared_ptr_pair_instance()
|
||||
{
|
||||
static thread_local auto& _pinst = get_shared_ptr_pair<Tp, Tag>();
|
||||
static thread_local auto& _inst = _pinst.second ? _pinst.second : _pinst.first;
|
||||
return _inst;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag, typename PtrT, typename PairT>
|
||||
PtrT
|
||||
get_shared_ptr_pair_main_instance()
|
||||
{
|
||||
static auto& _pinst = get_shared_ptr_pair<Tp, Tag>();
|
||||
static auto _inst = _pinst.first;
|
||||
return _inst;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag, typename PtrT>
|
||||
PtrT
|
||||
get_shared_ptr_lone_instance()
|
||||
{
|
||||
static auto _instance = std::make_shared<Tp>();
|
||||
return _instance;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace tim
|
||||
@@ -1,43 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(TIMEMORY_CORE_SOURCE)
|
||||
# define TIMEMORY_HASH_SOURCE
|
||||
#elif defined(TIMEMORY_USE_CORE_EXTERN)
|
||||
# define TIMEMORY_USE_HASH_EXTERN
|
||||
#endif
|
||||
//
|
||||
#if defined(TIMEMORY_USE_EXTERN) && !defined(TIMEMORY_USE_HASH_EXTERN)
|
||||
# define TIMEMORY_USE_HASH_EXTERN
|
||||
#endif
|
||||
//
|
||||
#if defined(TIMEMORY_HASH_SOURCE)
|
||||
# define TIMEMORY_HASH_LINKAGE(...) __VA_ARGS__
|
||||
#elif defined(TIMEMORY_USE_HASH_EXTERN)
|
||||
# define TIMEMORY_HASH_LINKAGE(...) extern __VA_ARGS__
|
||||
#else
|
||||
# define TIMEMORY_HASH_LINKAGE(...) inline __VA_ARGS__
|
||||
#endif
|
||||
@@ -1,290 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/api.hpp"
|
||||
#include "timemory/hash/macros.hpp"
|
||||
#include "timemory/macros/attributes.hpp"
|
||||
#include "timemory/macros/language.hpp"
|
||||
#include "timemory/mpl/concepts.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// GENERAL PURPOSE TLS DATA
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag = TIMEMORY_API, typename PtrT = std::shared_ptr<Tp>,
|
||||
typename PairT = std::pair<PtrT, PtrT>>
|
||||
PairT&
|
||||
get_shared_ptr_pair();
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag = TIMEMORY_API, typename PtrT = std::shared_ptr<Tp>,
|
||||
typename PairT = std::pair<PtrT, PtrT>>
|
||||
PtrT
|
||||
get_shared_ptr_pair_instance();
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag = TIMEMORY_API, typename PtrT = std::shared_ptr<Tp>,
|
||||
typename PairT = std::pair<PtrT, PtrT>>
|
||||
PtrT
|
||||
get_shared_ptr_pair_main_instance();
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename Tag = TIMEMORY_API, typename PtrT = std::shared_ptr<Tp>>
|
||||
PtrT
|
||||
get_shared_ptr_lone_instance();
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// HASH ALIASES
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
using hash_value_t = size_t;
|
||||
using hash_map_t = std::unordered_map<hash_value_t, std::string>;
|
||||
using hash_alias_map_t = std::unordered_map<hash_value_t, hash_value_t>;
|
||||
using hash_map_ptr_t = std::shared_ptr<hash_map_t>;
|
||||
using hash_map_ptr_pair_t = std::pair<hash_map_ptr_t, hash_map_ptr_t>;
|
||||
using hash_alias_ptr_t = std::shared_ptr<hash_alias_map_t>;
|
||||
using hash_resolver_t = std::function<bool(hash_value_t, std::string&)>;
|
||||
using hash_resolver_vec_t = std::vector<hash_resolver_t>;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// HASH DATA STRUCTURES
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
hash_map_ptr_t&
|
||||
get_hash_ids() TIMEMORY_HOT;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
hash_alias_ptr_t&
|
||||
get_hash_aliases() TIMEMORY_HOT;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
std::shared_ptr<hash_resolver_vec_t>&
|
||||
get_hash_resolvers() TIMEMORY_HOT;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// STRING -> HASH CONVERSION
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// declarations
|
||||
//
|
||||
template <typename Tp,
|
||||
std::enable_if_t<concepts::is_string_type<std::decay_t<Tp>>::value, int> = 0>
|
||||
TIMEMORY_INLINE hash_value_t
|
||||
get_hash_id(Tp&& _prefix);
|
||||
//
|
||||
template <typename Tp,
|
||||
std::enable_if_t<!concepts::is_string_type<std::decay_t<Tp>>::value, int> = 0>
|
||||
TIMEMORY_INLINE hash_value_t
|
||||
get_hash_id(Tp&& _prefix);
|
||||
//
|
||||
TIMEMORY_INLINE hash_value_t
|
||||
get_combined_hash_id(hash_value_t _lhs, hash_value_t _rhs);
|
||||
//
|
||||
template <typename Tp,
|
||||
std::enable_if_t<!std::is_integral<std::decay_t<Tp>>::value, int> = 0>
|
||||
TIMEMORY_INLINE hash_value_t
|
||||
get_combined_hash_id(hash_value_t _lhs, Tp&& _rhs);
|
||||
//
|
||||
// get hash of a string type
|
||||
//
|
||||
template <typename Tp,
|
||||
std::enable_if_t<concepts::is_string_type<std::decay_t<Tp>>::value, int>>
|
||||
hash_value_t
|
||||
get_hash_id(Tp&& _prefix)
|
||||
{
|
||||
return std::hash<string_view_t>{}(std::forward<Tp>(_prefix));
|
||||
}
|
||||
//
|
||||
// get hash of a non-string type
|
||||
//
|
||||
template <typename Tp,
|
||||
std::enable_if_t<!concepts::is_string_type<std::decay_t<Tp>>::value, int>>
|
||||
hash_value_t
|
||||
get_hash_id(Tp&& _prefix)
|
||||
{
|
||||
return std::hash<std::decay_t<Tp>>{}(std::forward<Tp>(_prefix));
|
||||
}
|
||||
//
|
||||
// combine two existing hashes
|
||||
//
|
||||
hash_value_t
|
||||
get_combined_hash_id(hash_value_t _lhs, hash_value_t _rhs)
|
||||
{
|
||||
return (_lhs ^= _rhs + 0x9e3779b9 + (_lhs << 6) + (_lhs >> 2));
|
||||
}
|
||||
//
|
||||
// compute the hash and combine it with an existing hash
|
||||
//
|
||||
template <typename Tp, std::enable_if_t<!std::is_integral<std::decay_t<Tp>>::value, int>>
|
||||
hash_value_t
|
||||
get_combined_hash_id(hash_value_t _lhs, Tp&& _rhs)
|
||||
{
|
||||
return get_combined_hash_id(_lhs, get_hash_id(std::forward<Tp>(_rhs)));
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
hash_value_t
|
||||
get_hash_id(const hash_alias_ptr_t& _hash_alias, hash_value_t _hash_id) TIMEMORY_HOT;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \fn hash_value_t add_hash_id(hash_map_ptr_t&, const string_view_t&)
|
||||
/// \brief add an string to the given hash-map (if it doesn't already exist) and return
|
||||
/// the hash
|
||||
///
|
||||
hash_value_t
|
||||
add_hash_id(hash_map_ptr_t& _hash_map, const string_view_t& _prefix) TIMEMORY_HOT;
|
||||
//
|
||||
inline hash_value_t
|
||||
add_hash_id(hash_map_ptr_t& _hash_map, const string_view_t& _prefix)
|
||||
{
|
||||
hash_value_t _hash_id = get_hash_id(_prefix);
|
||||
if(_hash_map && _hash_map->find(_hash_id) == _hash_map->end())
|
||||
{
|
||||
(*_hash_map)[_hash_id] = std::string{ _prefix };
|
||||
}
|
||||
return _hash_id;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \fn hash_value_t add_hash_id(const string_view_t&)
|
||||
/// \brief add an string to the default hash-map (if it doesn't already exist) and return
|
||||
/// the hash
|
||||
///
|
||||
hash_value_t
|
||||
add_hash_id(const string_view_t& _prefix) TIMEMORY_HOT;
|
||||
//
|
||||
inline hash_value_t
|
||||
add_hash_id(const string_view_t& _prefix)
|
||||
{
|
||||
return add_hash_id(get_hash_ids(), _prefix);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
void
|
||||
add_hash_id(const hash_map_ptr_t& _hash_map, const hash_alias_ptr_t& _hash_alias,
|
||||
hash_value_t _hash_id, hash_value_t _alias_hash_id) TIMEMORY_HOT;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
void
|
||||
add_hash_id(hash_value_t _hash_id, hash_value_t _alias_hash_id) TIMEMORY_HOT;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// HASH -> STRING CONVERSION
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \fn string_view_t get_hash_identifier_fast(hash_value_t)
|
||||
/// \brief this does not check other threads or aliases. Only call this function when
|
||||
/// you know that the hash exists on the thread and is not an alias
|
||||
//
|
||||
string_view_t
|
||||
get_hash_identifier_fast(hash_value_t _hash) TIMEMORY_HOT;
|
||||
//
|
||||
inline string_view_t
|
||||
get_hash_identifier_fast(hash_value_t _hash)
|
||||
{
|
||||
auto& _hash_ids = get_hash_ids();
|
||||
auto itr = _hash_ids->find(_hash);
|
||||
if(itr != _hash_ids->end())
|
||||
return itr->second;
|
||||
return "";
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
std::string
|
||||
get_hash_identifier(const hash_map_ptr_t& _hash_map, const hash_alias_ptr_t& _hash_alias,
|
||||
hash_value_t _hash_id);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
std::string
|
||||
get_hash_identifier(hash_value_t _hash_id);
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename FuncT>
|
||||
size_t
|
||||
add_hash_resolver(FuncT&& _func)
|
||||
{
|
||||
auto _resolvers = get_hash_resolvers();
|
||||
if(!_resolvers)
|
||||
return 0;
|
||||
_resolvers->emplace_back(std::forward<FuncT>(_func));
|
||||
return _resolvers->size();
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// HASH STRING DEMANGLING
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
std::string
|
||||
demangle_hash_identifier(std::string, char bdelim = '[', char edelim = ']');
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename... Args>
|
||||
auto
|
||||
get_demangled_hash_identifier(Args&&... _args)
|
||||
{
|
||||
return demangle_hash_identifier(get_hash_identifier(std::forward<Args>(_args)...));
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace tim
|
||||
@@ -1,193 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/macros/compiler.hpp"
|
||||
#include "timemory/macros/language.hpp"
|
||||
#include "timemory/macros/os.hpp"
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_ATTRIBUTE)
|
||||
# if defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_ATTRIBUTE(...) __declspec(__VA_ARGS__)
|
||||
# else
|
||||
# define TIMEMORY_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_ALWAYS_INLINE)
|
||||
# if defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_ALWAYS_INLINE __forceinline
|
||||
# else
|
||||
# define TIMEMORY_ALWAYS_INLINE TIMEMORY_ATTRIBUTE(always_inline) inline
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_INLINE)
|
||||
# define TIMEMORY_INLINE TIMEMORY_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_NODISCARD)
|
||||
# if defined(CXX17)
|
||||
# define TIMEMORY_NODISCARD [[nodiscard]]
|
||||
# else
|
||||
# define TIMEMORY_NODISCARD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_FLATTEN)
|
||||
# if !defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_FLATTEN [[gnu::flatten]]
|
||||
# else
|
||||
# define TIMEMORY_FLATTEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_HOT)
|
||||
# if !defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_HOT TIMEMORY_ATTRIBUTE(hot)
|
||||
# else
|
||||
# define TIMEMORY_HOT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_COLD)
|
||||
# if !defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_COLD TIMEMORY_ATTRIBUTE(cold)
|
||||
# else
|
||||
# define TIMEMORY_COLD
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_CONST)
|
||||
# define TIMEMORY_CONST [[gnu::const]]
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DEPRECATED)
|
||||
# define TIMEMORY_DEPRECATED(...) [[gnu::deprecated(__VA_ARGS__)]]
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_EXTERN_VISIBLE)
|
||||
# define TIMEMORY_EXTERN_VISIBLE [[gnu::externally_visible]]
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_HIDDEN)
|
||||
# if !defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_HIDDEN TIMEMORY_ATTRIBUTE(visibility("hidden"))
|
||||
# else
|
||||
# define TIMEMORY_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_ALIAS)
|
||||
# define TIMEMORY_ALIAS(...) [[gnu::alias(__VA_ARGS__)]]
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_NOINLINE)
|
||||
# define TIMEMORY_NOINLINE TIMEMORY_ATTRIBUTE(noinline)
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_NOCLONE)
|
||||
# if defined(TIMEMORY_GNU_COMPILER)
|
||||
# define TIMEMORY_NOCLONE TIMEMORY_ATTRIBUTE(noclone)
|
||||
# else
|
||||
# define TIMEMORY_NOCLONE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_HOT_INLINE)
|
||||
# define TIMEMORY_HOT_INLINE TIMEMORY_HOT TIMEMORY_INLINE
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DATA_ALIGNMENT)
|
||||
# define TIMEMORY_DATA_ALIGNMENT 8
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_PACKED_ALIGNMENT)
|
||||
# if defined(_WIN32) // Windows 32- and 64-bit
|
||||
# define TIMEMORY_PACKED_ALIGNMENT __declspec(align(TIMEMORY_DATA_ALIGNMENT))
|
||||
# elif defined(__GNUC__) // GCC
|
||||
# define TIMEMORY_PACKED_ALIGNMENT \
|
||||
__attribute__((__packed__)) __attribute__((aligned(TIMEMORY_DATA_ALIGNMENT)))
|
||||
# else // all other compilers
|
||||
# define TIMEMORY_PACKED_ALIGNMENT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
// device decorators
|
||||
//
|
||||
#if defined(__CUDACC__) || defined(__HIPCC__)
|
||||
# define TIMEMORY_LAMBDA __host__ __device__
|
||||
# define TIMEMORY_HOST_LAMBDA __host__
|
||||
# define TIMEMORY_HOST_FUNCTION __host__
|
||||
# define TIMEMORY_DEVICE_LAMBDA __device__
|
||||
# define TIMEMORY_DEVICE_FUNCTION __device__
|
||||
# define TIMEMORY_GLOBAL_FUNCTION __global__
|
||||
# define TIMEMORY_HOST_DEVICE_FUNCTION __host__ __device__
|
||||
# define TIMEMORY_DEVICE_INLINE __device__ __inline__
|
||||
# define TIMEMORY_GLOBAL_INLINE __global__ __inline__
|
||||
# define TIMEMORY_HOST_DEVICE_INLINE __host__ __device__ __inline__
|
||||
#else
|
||||
# define TIMEMORY_LAMBDA
|
||||
# define TIMEMORY_HOST_LAMBDA
|
||||
# define TIMEMORY_HOST_FUNCTION
|
||||
# define TIMEMORY_DEVICE_LAMBDA
|
||||
# define TIMEMORY_DEVICE_FUNCTION
|
||||
# define TIMEMORY_GLOBAL_FUNCTION
|
||||
# define TIMEMORY_HOST_DEVICE_FUNCTION
|
||||
# define TIMEMORY_DEVICE_INLINE inline
|
||||
# define TIMEMORY_GLOBAL_INLINE inline
|
||||
# define TIMEMORY_HOST_DEVICE_INLINE inline
|
||||
#endif
|
||||
@@ -1,205 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/macros/os.hpp"
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Compiler
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// clang compiler
|
||||
#if defined(__clang__) && !defined(TIMEMORY_CLANG_COMPILER)
|
||||
# define TIMEMORY_CLANG_COMPILER 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// GNU compiler
|
||||
#if defined(__GNUC__) && !defined(TIMEMORY_CLANG_COMPILER) && \
|
||||
!defined(TIMEMORY_GNU_COMPILER)
|
||||
# if(__GNUC__ <= 4 && __GNUC_MINOR__ < 9)
|
||||
# warning "GCC compilers < 4.9 have been known to have compiler errors"
|
||||
# define TIMEMORY_GNU_COMPILER 1
|
||||
# elif(__GNUC__ >= 4 && __GNUC_MINOR__ >= 9) || __GNUC__ >= 5
|
||||
# define TIMEMORY_GNU_COMPILER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// Intel compiler
|
||||
#if defined(__INTEL_COMPILER) && !defined(TIMEMORY_INTEL_COMPILER)
|
||||
# define TIMEMORY_INTEL_COMPILER 1
|
||||
# if __INTEL_COMPILER < 1500
|
||||
# warning "Intel compilers < 1500 have been known to have compiler errors"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// nvcc compiler
|
||||
#if defined(__NVCC__) && !defined(TIMEMORY_NVCC_COMPILER)
|
||||
# define TIMEMORY_NVCC_COMPILER 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// cuda compilation mode
|
||||
#if defined(__CUDACC__) && !defined(TIMEMORY_CUDACC)
|
||||
# define TIMEMORY_CUDACC 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// hcc or hip-clang compiler
|
||||
#if(defined(__HCC__) || (defined(__clang__) && defined(__HIP__))) && \
|
||||
!defined(TIMEMORY_HIP_COMPILER)
|
||||
# define TIMEMORY_HIP_COMPILER 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// hip compilation mode
|
||||
#if defined(__HIPCC__) && !defined(TIMEMORY_HIPCC)
|
||||
# define TIMEMORY_HIPCC 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// gpu compilation mode (may be host or device code)
|
||||
#if(defined(__CUDACC__) || defined(__HIPCC__)) && !defined(TIMEMORY_GPUCC)
|
||||
# define TIMEMORY_GPUCC 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// cuda compilation - device code
|
||||
#if defined(__CUDA_ARCH__) && !defined(TIMEMORY_CUDA_DEVICE_COMPILE)
|
||||
# define TIMEMORY_CUDA_DEVICE_COMPILE 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// hip compilation - device code
|
||||
#if defined(__HIP_DEVICE_COMPILE__) && !defined(TIMEMORY_HIP_DEVICE_COMPILE)
|
||||
# define TIMEMORY_HIP_DEVICE_COMPILE 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// gpu compiler - device code
|
||||
#if(defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__)) && \
|
||||
!defined(TIMEMORY_GPU_DEVICE_COMPILE)
|
||||
# define TIMEMORY_GPU_DEVICE_COMPILE 1
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// assume openmp target is enabled
|
||||
// #if defined(TIMEMORY_CUDACC) && defined(_OPENMP) && !defined(TIMEMORY_OPENMP_TARGET)
|
||||
// # define TIMEMORY_OPENMP_TARGET 1
|
||||
// #endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// MSVC compiler
|
||||
#if defined(_MSC_VER) && _MSC_VER > 0 && !defined(TIMEMORY_MSVC_COMPILER)
|
||||
# define TIMEMORY_MSVC_COMPILER 1
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Demangling
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if(defined(TIMEMORY_GNU_COMPILER) || defined(TIMEMORY_CLANG_COMPILER) || \
|
||||
defined(TIMEMORY_INTEL_COMPILER) || defined(TIMEMORY_NVCC_COMPILER) || \
|
||||
defined(TIMEMORY_HIP_COMPILER)) && \
|
||||
defined(TIMEMORY_UNIX)
|
||||
# if !defined(TIMEMORY_ENABLE_DEMANGLE)
|
||||
# define TIMEMORY_ENABLE_DEMANGLE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// WINDOWS WARNINGS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if defined(TIMEMORY_MSVC_COMPILER) && !defined(TIMEMORY_MSVC_WARNINGS)
|
||||
|
||||
# pragma warning(disable : 4003) // not enough actual params
|
||||
# pragma warning(disable : 4061) // enum in switch of enum not explicitly handled
|
||||
# pragma warning(disable : 4068) // unknown pragma
|
||||
# pragma warning(disable : 4127) // conditional expr is constant
|
||||
# pragma warning(disable : 4129) // unrecognized char escape
|
||||
# pragma warning(disable : 4146) // unsigned
|
||||
# pragma warning(disable : 4217) // locally defined symbol
|
||||
# pragma warning(disable : 4244) // possible loss of data
|
||||
# pragma warning(disable : 4251) // needs to have dll-interface to be used
|
||||
# pragma warning(disable : 4242) // possible loss of data (assignment)
|
||||
# pragma warning(disable : 4244) // conversion from 'double' to 'LONGLONG'
|
||||
# pragma warning(disable : 4245) // signed/unsigned mismatch (init conversion)
|
||||
# pragma warning(disable : 4267) // possible loss of data (implicit conversion)
|
||||
# pragma warning(disable : 4305) // truncation from 'double' to 'float'
|
||||
# pragma warning(disable : 4355) // this used in base member init list
|
||||
# pragma warning(disable : 4365) // signed/unsigned mismatch
|
||||
# pragma warning(disable : 4464) // relative include path contains '..'
|
||||
# pragma warning(disable : 4522) // multiple assignment operators specified
|
||||
# pragma warning(disable : 4625) // copy ctor implicitly defined as deleted
|
||||
# pragma warning(disable : 4626) // copy assign implicitly defined as deleted
|
||||
# pragma warning(disable : 4661) // no suitable definition for template inst
|
||||
# pragma warning(disable : 4700) // uninitialized local variable used
|
||||
# pragma warning(disable : 4710) // function not inlined
|
||||
# pragma warning(disable : 4711) // function selected for auto inline expansion
|
||||
# pragma warning(disable : 4786) // ID truncated to '255' char in debug info
|
||||
# pragma warning(disable : 4820) // bytes padded after data member
|
||||
# pragma warning(disable : 4834) // discarding return value with 'nodiscard'
|
||||
# pragma warning(disable : 4996) // function may be unsafe
|
||||
# pragma warning(disable : 5219) // implicit conversion; possible loss of data
|
||||
# pragma warning(disable : 5026) // move ctor implicitly defined as deleted
|
||||
# pragma warning(disable : 5027) // move assign implicitly defined as deleted
|
||||
# pragma warning(disable : 26495) // Always initialize member variable
|
||||
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// DISABLE WINDOWS MIN/MAX macros
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64)
|
||||
|
||||
# if !defined(NOMINMAX)
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
|
||||
#endif
|
||||
@@ -1,105 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// LANGUAGE
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// Define C++20
|
||||
#if !defined(CXX20)
|
||||
# if __cplusplus > 201703L // C++20
|
||||
# define CXX20
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// Define C++17
|
||||
#if !defined(CXX17)
|
||||
# if __cplusplus > 201402L // C++17
|
||||
# define CXX17
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// Define C++14
|
||||
#if !defined(CXX14)
|
||||
# if __cplusplus > 201103L // C++14
|
||||
# define CXX14
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if !defined(CXX14)
|
||||
# if !defined(TIMEMORY_WINDOWS)
|
||||
# error "timemory requires __cplusplus > 201103L (C++14)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if !defined(IF_CONSTEXPR)
|
||||
# if defined(CXX17)
|
||||
# define IF_CONSTEXPR(...) if constexpr(__VA_ARGS__)
|
||||
# else
|
||||
# define IF_CONSTEXPR(...) if(__VA_ARGS__)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if defined(CXX17)
|
||||
# include <string_view>
|
||||
//
|
||||
# if !defined(TIMEMORY_STRING_VIEW)
|
||||
# define TIMEMORY_STRING_VIEW 1
|
||||
# endif
|
||||
//
|
||||
namespace tim
|
||||
{
|
||||
using string_view_t = std::string_view;
|
||||
}
|
||||
//
|
||||
#else
|
||||
//
|
||||
# include <string>
|
||||
//
|
||||
# if !defined(TIMEMORY_STRING_VIEW)
|
||||
# define TIMEMORY_STRING_VIEW 0
|
||||
# endif
|
||||
//
|
||||
namespace tim
|
||||
{
|
||||
using string_view_t = std::string;
|
||||
}
|
||||
//
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -1,118 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Operating System
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if defined(__x86_64__)
|
||||
# if !defined(TIMEMORY_64BIT)
|
||||
# define TIMEMORY_64BIT 1
|
||||
# endif
|
||||
#else
|
||||
# if !defined(TIMEMORY_32BIT)
|
||||
# define TIMEMORY_32BIT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// timemory prefixed os preprocessor definitions
|
||||
//
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64)
|
||||
# if !defined(TIMEMORY_WINDOWS)
|
||||
# define TIMEMORY_WINDOWS 1
|
||||
# endif
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
# if !defined(TIMEMORY_MACOS)
|
||||
# define TIMEMORY_MACOS 1
|
||||
# endif
|
||||
# if !defined(TIMEMORY_UNIX)
|
||||
# define TIMEMORY_UNIX 1
|
||||
# endif
|
||||
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
|
||||
# if !defined(TIMEMORY_LINUX)
|
||||
# define TIMEMORY_LINUX 1
|
||||
# endif
|
||||
# if !defined(TIMEMORY_UNIX)
|
||||
# define TIMEMORY_UNIX 1
|
||||
# endif
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix)
|
||||
# if !defined(TIMEMORY_UNIX)
|
||||
# define TIMEMORY_UNIX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// non-timemory prefixed os preprocessor definitions (deprecated)
|
||||
//
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64)
|
||||
# if !defined(_WINDOWS)
|
||||
# define _WINDOWS 1
|
||||
# endif
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
# if !defined(_MACOS)
|
||||
# define _MACOS 1
|
||||
# endif
|
||||
# if !defined(_UNIX)
|
||||
# define _UNIX 1
|
||||
# endif
|
||||
#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
|
||||
# if !defined(_LINUX)
|
||||
# define _LINUX 1
|
||||
# endif
|
||||
# if !defined(_UNIX)
|
||||
# define _UNIX 1
|
||||
# endif
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix)
|
||||
# if !defined(_UNIX)
|
||||
# define _UNIX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// this ensures that winnt.h never causes a 64-bit build to fail
|
||||
// also solves issue with ws2def.h and winsock2.h:
|
||||
// https://www.zachburlingame.com/2011/05/
|
||||
// resolving-redefinition-errors-betwen-ws2def-h-and-winsock-h/
|
||||
#if defined(_WINDOWS)
|
||||
# if !defined(NOMINMAX)
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# if !defined(WIN32_LEAN_AND_MEAN)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# if !defined(WIN32)
|
||||
# define WIN32
|
||||
# endif
|
||||
# if defined(TIMEMORY_USE_WINSOCK)
|
||||
# include <WinSock2.h>
|
||||
# endif
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -1,684 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/macros/attributes.hpp"
|
||||
#include "timemory/mpl/math.hpp"
|
||||
#include "timemory/mpl/stl.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
namespace tim
|
||||
{
|
||||
// clang-format off
|
||||
namespace device { struct cpu; struct gpu; } // namespace device
|
||||
// clang-format on
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template <typename Ret>
|
||||
struct apply
|
||||
{
|
||||
//----------------------------------------------------------------------------------//
|
||||
// invoke a function with a tuple
|
||||
//
|
||||
template <typename Fn, typename Tuple, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE Ret invoke(Fn&& __f, Tuple&& __t, index_sequence<Idx...>)
|
||||
{
|
||||
return __f(std::get<Idx>(std::forward<Tuple>(__t))...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// prefix with _sep
|
||||
//
|
||||
template <typename SepT, typename Arg,
|
||||
enable_if_t<std::is_same<Ret, std::string>::value, char> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join_tail(std::stringstream& _ss, const SepT& _sep,
|
||||
Arg&& _arg)
|
||||
{
|
||||
_ss << _sep << std::forward<Arg>(_arg);
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// prefix with _sep
|
||||
//
|
||||
template <typename SepT, typename Arg, typename... Args,
|
||||
enable_if_t<std::is_same<Ret, std::string>::value, char> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join_tail(std::stringstream& _ss, const SepT& _sep,
|
||||
Arg&& _arg, Args&&... __args)
|
||||
{
|
||||
_ss << _sep << std::forward<Arg>(_arg);
|
||||
return join_tail<SepT, Args...>(_ss, _sep, std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// don't prefix
|
||||
//
|
||||
template <typename SepT, typename Arg,
|
||||
enable_if_t<std::is_same<Ret, std::string>::value, char> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join(std::stringstream& _ss, const SepT&, Arg&& _arg)
|
||||
{
|
||||
_ss << std::forward<Arg>(_arg);
|
||||
return _ss.str();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// don't prefix
|
||||
//
|
||||
template <typename SepT, typename Arg, typename... Args,
|
||||
enable_if_t<std::is_same<Ret, std::string>::value, char> = 0,
|
||||
enable_if_t<(sizeof...(Args) > 0), int> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join(std::stringstream& _ss, const SepT& _sep,
|
||||
Arg&& _arg, Args&&... __args)
|
||||
{
|
||||
_ss << std::forward<Arg>(_arg);
|
||||
return join_tail<SepT, Args...>(_ss, _sep, std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
template <>
|
||||
struct apply<void>
|
||||
{
|
||||
using Ret = void;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename Tail>
|
||||
struct get_index_of;
|
||||
|
||||
template <typename Tp, typename... Tail>
|
||||
struct get_index_of<Tp, std::tuple<Tp, Tail...>>
|
||||
{
|
||||
static constexpr int value = 0;
|
||||
};
|
||||
|
||||
template <typename Tp, typename... Tail>
|
||||
struct get_index_of<Tp, std::tuple<Tp*, Tail...>>
|
||||
{
|
||||
static constexpr int value = 0;
|
||||
};
|
||||
|
||||
template <typename Tp, typename... Tail>
|
||||
struct get_index_of<Tp, std::tuple<Tp&, Tail...>>
|
||||
{
|
||||
static constexpr int value = 0;
|
||||
};
|
||||
|
||||
template <typename Tp, typename Head, typename... Tail>
|
||||
struct get_index_of<Tp, std::tuple<Head, Tail...>>
|
||||
{
|
||||
static constexpr int value = 1 + get_index_of<Tp, std::tuple<Tail...>>::value;
|
||||
};
|
||||
|
||||
template <typename Tp, typename... Tail>
|
||||
struct get_index_of<Tp, std::tuple<Tail...>>
|
||||
{
|
||||
static_assert(sizeof...(Tail) != 0, "Error! Type not found!");
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// invoke a function with a tuple
|
||||
//
|
||||
template <typename Fn, typename Tuple, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE Ret invoke(Fn&& __f, Tuple&& __t, index_sequence<Idx...>)
|
||||
{
|
||||
__f(std::get<Idx>(std::forward<Tuple>(__t))...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// temporary construction
|
||||
//
|
||||
template <typename Type, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void construct(Args&&... _args)
|
||||
{
|
||||
Type(std::forward<Args>(_args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// temporary construction
|
||||
//
|
||||
template <typename Type, typename... Args, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void construct_tuple(std::tuple<Args...>&& _args,
|
||||
index_sequence<Idx>...)
|
||||
{
|
||||
construct<Type>(std::get<Idx>(_args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <template <typename> class Access, typename Tuple, typename... Args,
|
||||
size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void unroll_access(Tuple&& __t, index_sequence<Idx...>,
|
||||
Args&&... __args)
|
||||
{
|
||||
TIMEMORY_FOLD_EXPRESSION(Access<decay_t<decltype(std::get<Idx>(__t))>>(
|
||||
std::forward<decltype(std::get<Idx>(__t))>(std::get<Idx>(__t)),
|
||||
std::forward<Args>(__args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename Tuple, typename... Args, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void variadic_1d(Tuple&& __t, Args&&... _args,
|
||||
index_sequence<Idx...>)
|
||||
{
|
||||
TIMEMORY_FOLD_EXPRESSION(
|
||||
construct<typename std::tuple_element<Idx, Access>::type>(
|
||||
std::get<Idx>(__t), std::forward<Args>(_args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename TupleA, typename TupleB, typename... Args,
|
||||
size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void variadic_2d(TupleA&& __a, TupleB&& __b,
|
||||
Args&&... _args, index_sequence<Idx...>)
|
||||
{
|
||||
TIMEMORY_FOLD_EXPRESSION(
|
||||
construct<typename std::tuple_element<Idx, Access>::type>(
|
||||
std::get<Idx>(__a), std::get<Idx>(__b), std::forward<Args>(_args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <template <typename> class Access, typename Tuple, typename... Args,
|
||||
size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void type_access(index_sequence<Idx...>, Args&&... __args)
|
||||
{
|
||||
TIMEMORY_FOLD_EXPRESSION(
|
||||
Access<decay_t<typename std::tuple_element<Idx, Tuple>::type>>(
|
||||
std::forward<Args>(__args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename Tuple, typename... Args, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void apply_access_with_indices(Tuple&& __t,
|
||||
index_sequence<Idx...>,
|
||||
Args&&... __args)
|
||||
{
|
||||
// call constructor
|
||||
TIMEMORY_FOLD_EXPRESSION(decay_t<typename std::tuple_element<Idx, Access>::type>(
|
||||
Idx, sizeof...(Idx),
|
||||
std::forward<decltype(std::get<Idx>(__t))>(std::get<Idx>(__t)),
|
||||
std::forward<Args>(__args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename TupleA, typename TupleB, typename... Args,
|
||||
size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void apply_access2(TupleA&& __ta, TupleB&& __tb,
|
||||
index_sequence<Idx...>,
|
||||
Args&&... __args)
|
||||
{
|
||||
// call constructor
|
||||
TIMEMORY_FOLD_EXPRESSION(decay_t<typename std::tuple_element<Idx, Access>::type>(
|
||||
std::forward<decltype(std::get<Idx>(__ta))>(std::get<Idx>(__ta)),
|
||||
std::forward<decltype(std::get<Idx>(__tb))>(std::get<Idx>(__tb)),
|
||||
std::forward<Args>(__args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// unroll
|
||||
template <size_t N, typename Device, typename Func, typename... Args,
|
||||
typename std::enable_if<
|
||||
(N == 1 && std::is_same<Device, device::gpu>::value), char>::type = 0>
|
||||
TIMEMORY_LAMBDA static void unroll(Func&& __func, Args&&... __args)
|
||||
{
|
||||
std::forward<Func>(__func)(std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
template <size_t N, typename Device, typename Func, typename... Args,
|
||||
typename std::enable_if<(N > 1 && std::is_same<Device, device::gpu>::value),
|
||||
char>::type = 0>
|
||||
TIMEMORY_LAMBDA static void unroll(Func&& __func, Args&&... __args)
|
||||
{
|
||||
std::forward<Func>(__func)(std::forward<Args>(__args)...);
|
||||
unroll<N - 1, Device, Func, Args...>(std::forward<Func>(__func),
|
||||
std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// unroll
|
||||
template <size_t N, typename Device, typename Func, typename... Args,
|
||||
typename std::enable_if<
|
||||
(N == 1 && std::is_same<Device, device::cpu>::value), int>::type = 0>
|
||||
static TIMEMORY_HOT_INLINE void unroll(Func&& __func, Args&&... __args)
|
||||
{
|
||||
std::forward<Func>(__func)(std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
template <size_t N, typename Device, typename Func, typename... Args,
|
||||
typename std::enable_if<(N > 1 && std::is_same<Device, device::cpu>::value),
|
||||
int>::type = 0>
|
||||
static TIMEMORY_HOT_INLINE void unroll(Func&& __func, Args&&... __args)
|
||||
{
|
||||
std::forward<Func>(__func)(std::forward<Args>(__args)...);
|
||||
unroll<N - 1, Device, Func, Args...>(std::forward<Func>(__func),
|
||||
std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
} // namespace internal
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Declaration
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
namespace mpl
|
||||
{
|
||||
template <typename Ret>
|
||||
struct apply;
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// apply --> std::string
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
template <>
|
||||
struct apply<std::string>
|
||||
{
|
||||
using Ret = std::string;
|
||||
using string_t = std::string;
|
||||
using string_tuple_t = std::tuple<std::string>;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// Helper
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, bool _Val = true, typename Up = int,
|
||||
typename Dt = typename std::remove_const<decay_t<Tp>>::type>
|
||||
using if_string_t = enable_if_t<std::is_same<Dt, char*>::value == _Val, Up>;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename SepT, typename... Args, typename ReturnT = Ret,
|
||||
size_t N = sizeof...(Args), enable_if_t<(N > 0), char> = 0>
|
||||
static TIMEMORY_HOT_INLINE ReturnT join(SepT&& separator, Args&&... __args) noexcept
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::boolalpha;
|
||||
return internal::apply<Ret>::template join<SepT, Args...>(
|
||||
std::ref(ss), std::forward<SepT>(separator), std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename SepT, typename Arg, if_string_t<Arg, true> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join(SepT&&, Arg&& _arg) noexcept
|
||||
{
|
||||
return std::forward<Arg>(_arg);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename SepT, typename Arg, if_string_t<Arg, false> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join(SepT&&, Arg&& _arg) noexcept
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << _arg;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
static TIMEMORY_HOT_INLINE Ret join(const string_t&) noexcept { return Ret{}; }
|
||||
static TIMEMORY_HOT_INLINE Ret join(const char) noexcept { return Ret{}; }
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// apply --> generic
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
template <typename Ret>
|
||||
struct apply
|
||||
{
|
||||
using string_t = std::string;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// invoke a function
|
||||
//
|
||||
template <typename Fn, typename... Args, size_t N = sizeof...(Args)>
|
||||
static TIMEMORY_HOT_INLINE Ret invoke(Fn&& __f, Args&&... __args) noexcept
|
||||
{
|
||||
return __f(std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// invoke a function with a tuple
|
||||
//
|
||||
template <typename Fn, template <typename...> class Tuple, typename... Args,
|
||||
size_t N = sizeof...(Args)>
|
||||
static TIMEMORY_HOT_INLINE Ret invoke(Fn&& __f, Tuple<Args...>&& __t) noexcept
|
||||
{
|
||||
using Tuple_t = Tuple<Args...>;
|
||||
return internal::apply<Ret>::template invoke<Fn, Tuple_t>(
|
||||
std::forward<Fn>(__f), std::forward<Tuple_t>(__t), make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename SepT, typename Tuple, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE string_t join(SepT&& separator, Tuple&& __tup,
|
||||
index_sequence<Idx...>) noexcept
|
||||
{
|
||||
return apply<string_t>::join(separator, std::get<Idx>(__tup)...);
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// apply --> std::tuple<std::string>
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
template <>
|
||||
struct apply<std::tuple<std::string>>
|
||||
{
|
||||
using string_t = std::string;
|
||||
using Ret = string_t;
|
||||
using apply_v = apply<string_t>;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// implementation for label + entry join
|
||||
//
|
||||
struct impl
|
||||
{
|
||||
template <typename LabelSep, typename EntrySep, typename LabelTup,
|
||||
typename EntryTup, size_t... Idx>
|
||||
static Ret join(LabelSep&& _label_sep, EntrySep&& _entry_sep,
|
||||
LabelTup&& _label_tup, EntryTup&& _entry_tup,
|
||||
index_sequence<Idx...>) noexcept
|
||||
{
|
||||
return apply_v::join(std::forward<LabelSep>(_label_sep),
|
||||
apply_v::join(std::forward<EntrySep>(_entry_sep),
|
||||
std::get<Idx>(_label_tup),
|
||||
std::get<Idx>(_entry_tup))...);
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// join a tuple of labels with entries
|
||||
//
|
||||
template <typename LabelSep, typename EntrySep, typename LabelTup, typename EntryTup,
|
||||
size_t N = std::tuple_size<decay_t<LabelTup>>::value,
|
||||
enable_if_t<(N > 0), int> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join(LabelSep&& _label_sep, EntrySep&& _entry_sep,
|
||||
LabelTup&& _label_tup,
|
||||
EntryTup&& _entry_tup) noexcept
|
||||
{
|
||||
// clang-format off
|
||||
return impl::join(std::forward<LabelSep>(_label_sep),
|
||||
std::forward<EntrySep>(_entry_sep),
|
||||
std::forward<LabelTup>(_label_tup),
|
||||
std::forward<EntryTup>(_entry_tup),
|
||||
make_index_sequence<N>{});
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// join a tuple of labels with entries
|
||||
//
|
||||
template <typename LabelSep, typename EntrySep, typename LabelTup, typename EntryTup,
|
||||
size_t N = std::tuple_size<decay_t<LabelTup>>::value,
|
||||
enable_if_t<N == 0, int> = 0>
|
||||
static TIMEMORY_HOT_INLINE Ret join(LabelSep&&, EntrySep&&, LabelTup&&,
|
||||
EntryTup&&) noexcept
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
};
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// apply --> void
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
template <>
|
||||
struct apply<void>
|
||||
{
|
||||
using Ret = void;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <size_t I, typename A>
|
||||
using Access_t = typename std::tuple_element<I, A>::type;
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// invoke a function
|
||||
//
|
||||
template <typename Fn, typename... Args, size_t N = sizeof...(Args)>
|
||||
static TIMEMORY_HOT_INLINE Ret invoke(Fn&& __f, Args&&... __args) noexcept
|
||||
{
|
||||
__f(std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// invoke a function with a tuple
|
||||
//
|
||||
template <typename Fn, template <typename...> class Tuple, typename... Args,
|
||||
size_t N = sizeof...(Args)>
|
||||
static TIMEMORY_HOT_INLINE Ret invoke(Fn&& __f, Tuple<Args...>&& __t) noexcept
|
||||
{
|
||||
using Tuple_t = Tuple<Args...>;
|
||||
internal::apply<Ret>::template invoke<Fn, Tuple_t>(
|
||||
std::forward<Fn>(__f), std::forward<Tuple_t>(__t), make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// per-element addition
|
||||
//
|
||||
template <typename Tuple, size_t N = std::tuple_size<Tuple>::value>
|
||||
static TIMEMORY_HOT_INLINE void plus(Tuple& _lhs, const Tuple& _rhs) noexcept
|
||||
{
|
||||
math::plus(_lhs, _rhs);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
// per-element subtraction
|
||||
//
|
||||
template <typename Tuple, size_t N = std::tuple_size<Tuple>::value>
|
||||
static TIMEMORY_HOT_INLINE void minus(Tuple& _lhs, const Tuple& _rhs) noexcept
|
||||
{
|
||||
math::minus(_lhs, _rhs);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <size_t N, typename Device, typename Func, typename... Args,
|
||||
enable_if_t<std::is_same<Device, device::gpu>::value, char> = 0>
|
||||
TIMEMORY_LAMBDA static void unroll(Func&& __func, Args&&... __args) noexcept
|
||||
{
|
||||
internal::apply<void>::template unroll<N, Device, Func, Args...>(
|
||||
std::forward<Func>(__func), std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <size_t N, typename Device, typename Func, typename... Args,
|
||||
enable_if_t<std::is_same<Device, device::cpu>::value, char> = 0>
|
||||
static TIMEMORY_HOT_INLINE void unroll(Func&& __func, Args&&... __args) noexcept
|
||||
{
|
||||
internal::apply<void>::template unroll<N, Device, Func, Args...>(
|
||||
std::forward<Func>(__func), std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
//
|
||||
// N > 0
|
||||
//
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename Value>
|
||||
static TIMEMORY_HOT_INLINE auto set_value_fold(Tp&& _t, int, Value&& _v) noexcept
|
||||
-> decltype(std::forward<Tp>(_t) = std::forward<Value>(_v), void())
|
||||
{
|
||||
std::forward<Tp>(_t) = std::forward<Value>(_v);
|
||||
}
|
||||
|
||||
template <typename Tp, typename Value>
|
||||
static TIMEMORY_HOT_INLINE void set_value_fold(Tp&&, long, Value&&) noexcept
|
||||
{}
|
||||
|
||||
template <typename Tuple, typename Value, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE void set_value_fold(Tuple&& _t, Value&& _v,
|
||||
index_sequence<Idx...>) noexcept
|
||||
{
|
||||
TIMEMORY_FOLD_EXPRESSION(
|
||||
set_value_fold(std::get<Idx>(_t), 0, std::forward<Value>(_v)));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tuple, typename Value>
|
||||
static TIMEMORY_HOT_INLINE void set_value(Tuple&& _t, Value&& _v) noexcept
|
||||
{
|
||||
constexpr auto N = std::tuple_size<decay_t<Tuple>>::value;
|
||||
set_value_fold(std::forward<Tuple>(_t), std::forward<Value>(_v),
|
||||
make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename Tuple, size_t... Idx, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void access_fold(Tuple&& _t, index_sequence<Idx...>,
|
||||
Args&&... _args)
|
||||
{
|
||||
TIMEMORY_FOLD_EXPRESSION(
|
||||
Access_t<Idx, Access>(std::get<Idx>(_t), std::forward<Args>(_args)...));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename Tuple, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void access(Tuple&& __t, Args&&... __args) noexcept
|
||||
{
|
||||
constexpr auto N = std::tuple_size<decay_t<Access>>::value;
|
||||
constexpr auto Nt = std::tuple_size<decay_t<Tuple>>::value;
|
||||
static_assert(N == Nt, "Cannot fold Access from Tuple because sizes differ");
|
||||
access_fold<Access>(std::forward<Tuple>(__t), std::make_index_sequence<N>{},
|
||||
std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, size_t... Idx, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE auto get_fold(index_sequence<Idx...>, Args&&... _args)
|
||||
{
|
||||
return std::make_tuple(
|
||||
Access_t<Idx, Access>::get(std::forward<Args>(_args)...)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE auto get(Args&&... __args)
|
||||
{
|
||||
constexpr auto N = std::tuple_size<decay_t<Access>>::value;
|
||||
return get_fold<Access>(std::make_index_sequence<N>{},
|
||||
std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename Tuple, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void access_with_indices(Tuple&& __t,
|
||||
Args&&... __args) noexcept
|
||||
{
|
||||
constexpr auto N = std::tuple_size<decay_t<Tuple>>::value;
|
||||
internal::apply<void>::template apply_access_with_indices<Access, Tuple, Args...>(
|
||||
std::forward<Tuple>(__t), make_index_sequence<N>{},
|
||||
std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Access, typename TupleA, typename TupleB, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void access2(TupleA&& __ta, TupleB&& __tb,
|
||||
Args&&... __args) noexcept
|
||||
{
|
||||
constexpr size_t N = std::tuple_size<decay_t<Access>>::value;
|
||||
constexpr size_t Na = std::tuple_size<decay_t<TupleA>>::value;
|
||||
constexpr size_t Nb = std::tuple_size<decay_t<TupleB>>::value;
|
||||
static_assert(Na == Nb, "tuple A size must match tuple B size");
|
||||
internal::apply<void>::template apply_access2<Access, TupleA, TupleB, Args...>(
|
||||
std::forward<TupleA>(__ta), std::forward<TupleB>(__tb),
|
||||
make_index_sequence<N>{}, std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <template <typename> class Access, typename Tuple, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void unroll_access(Tuple&& __t, Args&&... __args) noexcept
|
||||
{
|
||||
constexpr size_t N = std::tuple_size<decay_t<Tuple>>::value;
|
||||
internal::apply<void>::template unroll_access<Access, Tuple, Args...>(
|
||||
std::forward<Tuple>(__t), make_index_sequence<N>{},
|
||||
std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
template <template <typename> class Access, typename Tuple, typename... Args>
|
||||
static TIMEMORY_HOT_INLINE void type_access(Args&&... __args) noexcept
|
||||
{
|
||||
constexpr size_t N = std::tuple_size<decay_t<Tuple>>::value;
|
||||
internal::apply<void>::template type_access<Access, Tuple, Args...>(
|
||||
make_index_sequence<N>{}, std::forward<Args>(__args)...);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
};
|
||||
//
|
||||
} // namespace mpl
|
||||
} // namespace tim
|
||||
@@ -1,461 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/mpl/bits/types.hpp"
|
||||
#include "timemory/mpl/math.hpp"
|
||||
#include "timemory/mpl/types.hpp"
|
||||
#include "timemory/utility/types.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename Lhs, typename Rhs>
|
||||
const pair<Lhs, Rhs>
|
||||
operator-(pair<Lhs, Rhs>, const pair<Lhs, Rhs>&);
|
||||
|
||||
template <typename... Types>
|
||||
const tuple<Types...>
|
||||
operator-(tuple<Types...>, const tuple<Types...>&);
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
namespace tim
|
||||
{
|
||||
/// \namespace tim::stl
|
||||
/// \brief the namespace is provided to hide stl overload from global namespace but
|
||||
/// provide a method of using the namespace without a "using namespace tim;"
|
||||
namespace stl
|
||||
{
|
||||
namespace ostream
|
||||
{
|
||||
/// \namespace tim::stl::ostream
|
||||
/// \brief the namespace provides overloads to output complex data types w/ streams
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator <<
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T, typename U>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const std::pair<T, U>& p)
|
||||
{
|
||||
os << "(" << p.first << "," << p.second << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename... Types>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const std::tuple<Types...>& p)
|
||||
{
|
||||
constexpr size_t N = sizeof...(Types);
|
||||
tuple_printer(p, os, make_index_sequence<N>{});
|
||||
return os;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... ExtraT>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const std::vector<Tp, ExtraT...>& p)
|
||||
{
|
||||
os << "(";
|
||||
for(size_t i = 0; i < p.size(); ++i)
|
||||
os << p.at(i) << ((i + 1 < p.size()) ? "," : "");
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const std::array<Tp, N>& p)
|
||||
{
|
||||
os << "(";
|
||||
for(size_t i = 0; i < p.size(); ++i)
|
||||
os << p.at(i) << ((i + 1 < p.size()) ? "," : "");
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace ostream
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator += (same type)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N, typename OtherT>
|
||||
std::array<Tp, N>&
|
||||
operator+=(std::array<Tp, N>& lhs, OtherT&& rhs)
|
||||
{
|
||||
math::plus(lhs, std::forward<OtherT>(rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename OtherT>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator+=(std::pair<Lhs, Rhs>& lhs, OtherT&& rhs)
|
||||
{
|
||||
math::plus(lhs, std::forward<OtherT>(rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... ExtraT, typename OtherT>
|
||||
std::vector<Tp, ExtraT...>&
|
||||
operator+=(std::vector<Tp, ExtraT...>& lhs, OtherT&& rhs)
|
||||
{
|
||||
math::plus(lhs, std::forward<OtherT>(rhs));
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types, typename OtherT>
|
||||
std::tuple<Types...>&
|
||||
operator+=(std::tuple<Types...>& lhs, OtherT&& rhs)
|
||||
{
|
||||
math::plus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator -= (same type)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator-=(std::array<Tp, N>& lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator-=(std::pair<Lhs, Rhs>& lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... ExtraT>
|
||||
std::vector<Tp, ExtraT...>&
|
||||
operator-=(std::vector<Tp, ExtraT...>& lhs, const std::vector<Tp, ExtraT...>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator-=(std::tuple<Types...>& lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator *= (same type)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator*=(std::array<Tp, N>& lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator*=(std::pair<Lhs, Rhs>& lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... ExtraT>
|
||||
std::vector<Tp, ExtraT...>&
|
||||
operator*=(std::vector<Tp, ExtraT...>& lhs, const std::vector<Tp, ExtraT...>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator*=(std::tuple<Types...>& lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator /= (same type)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator/=(std::array<Tp, N>& lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator/=(std::pair<Lhs, Rhs>& lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... ExtraT>
|
||||
std::vector<Tp, ExtraT...>&
|
||||
operator/=(std::vector<Tp, ExtraT...>& lhs, const std::vector<Tp, ExtraT...>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator/=(std::tuple<Types...>& lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator *= (fundamental)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, size_t N, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
std::array<Lhs, N>&
|
||||
operator*=(std::array<Lhs, N>& lhs, const Rhs& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename ArithT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<ArithT>>::value, int>>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator*=(std::pair<Lhs, Rhs>& lhs, const ArithT& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename... ExtraT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
std::vector<Lhs, ExtraT...>&
|
||||
operator*=(std::vector<Lhs, ExtraT...>& lhs, const Rhs& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
std::tuple<Lhs...>&
|
||||
operator*=(std::tuple<Lhs...>& lhs, const Rhs& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator /= (fundamental)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, size_t N, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
std::array<Lhs, N>&
|
||||
operator/=(std::array<Lhs, N>& lhs, const Rhs& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename ArithT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<ArithT>>::value, int>>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator/=(std::pair<Lhs, Rhs>& lhs, const ArithT& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename... ExtraT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
std::vector<Lhs, ExtraT...>&
|
||||
operator/=(std::vector<Lhs, ExtraT...>& lhs, const Rhs& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
std::tuple<Lhs...>&
|
||||
operator/=(std::tuple<Lhs...>& lhs, const Rhs& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator * (fundamental)
|
||||
// operator / (fundamental)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
Lhs operator*(Lhs lhs, const Rhs& rhs)
|
||||
{
|
||||
return (lhs *= rhs);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int>>
|
||||
Lhs
|
||||
operator/(Lhs lhs, const Rhs& rhs)
|
||||
{
|
||||
return (lhs /= rhs);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace stl
|
||||
|
||||
using namespace stl;
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
} // namespace tim
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
namespace std
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
const pair<Lhs, Rhs>
|
||||
operator-(pair<Lhs, Rhs> lhs, const pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
::tim::math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
const tuple<Types...>
|
||||
operator-(tuple<Types...> lhs, const tuple<Types...>& rhs)
|
||||
{
|
||||
::tim::math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename Tp>
|
||||
tuple<>&
|
||||
operator+=(tuple<>& _lhs, const Tp&)
|
||||
{
|
||||
return _lhs;
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
@@ -1,297 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \file mpl/bits/types.hpp
|
||||
* \headerfile mpl/bits/types.hpp "timemory/mpl/bits/types.hpp"
|
||||
*
|
||||
* This is a declaration of the STL overload types
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "timemory/mpl/types.hpp"
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace stl
|
||||
{
|
||||
namespace ostream
|
||||
{
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator <<
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T, typename U>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::pair<T, U>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::tuple<Types...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... _Extra>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::vector<Tp, _Extra...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::array<Tp, N>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <template <typename...> class _Tuple, typename... Types, size_t... Idx>
|
||||
void
|
||||
tuple_printer(const _Tuple<Types...>& obj, std::ostream& os, index_sequence<Idx...>)
|
||||
{
|
||||
using namespace ::tim::stl::ostream;
|
||||
constexpr size_t N = sizeof...(Types);
|
||||
|
||||
if(N > 0)
|
||||
os << "(";
|
||||
char delim[N];
|
||||
TIMEMORY_FOLD_EXPRESSION(delim[Idx] = ',');
|
||||
delim[N - 1] = '\0';
|
||||
TIMEMORY_FOLD_EXPRESSION(os << std::get<Idx>(obj) << delim[Idx]);
|
||||
if(N > 0)
|
||||
os << ")";
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace ostream
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator +=
|
||||
// operator +
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N, typename Other>
|
||||
std::array<Tp, N>&
|
||||
operator+=(std::array<Tp, N>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Other>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator+=(std::pair<Lhs, Rhs>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... _Extra, typename Other>
|
||||
std::vector<Tp, _Extra...>&
|
||||
operator+=(std::vector<Tp, _Extra...>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types, typename Other>
|
||||
std::tuple<Types...>&
|
||||
operator+=(std::tuple<Types...>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator -=
|
||||
// operator -
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator-=(std::array<Tp, N>&, const std::array<Tp, N>&);
|
||||
|
||||
template <typename Lhs, size_t N, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::array<Lhs, N>&
|
||||
operator-=(std::array<Lhs, N>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator-=(std::pair<Lhs, Rhs>&, const std::pair<Lhs, Rhs>&);
|
||||
|
||||
template <typename Lhs, typename Rhs, typename ArithT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<ArithT>>::value, int> = 0>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator-=(std::pair<Lhs, Rhs>&, const ArithT&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... _Extra>
|
||||
std::vector<Tp, _Extra...>&
|
||||
operator-=(std::vector<Tp, _Extra...>&, const std::vector<Tp, _Extra...>&);
|
||||
|
||||
template <typename Lhs, typename Rhs, typename... _Extra,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::vector<Lhs, _Extra...>&
|
||||
operator-=(std::vector<Lhs, _Extra...>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator-=(std::tuple<Types...>&, const std::tuple<Types...>&);
|
||||
|
||||
template <typename... Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::tuple<Lhs...>&
|
||||
operator-=(std::tuple<Lhs...>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator *=
|
||||
// operator *
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator*=(std::array<Tp, N>&, const std::array<Tp, N>&);
|
||||
|
||||
template <typename Lhs, size_t N, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::array<Lhs, N>&
|
||||
operator*=(std::array<Lhs, N>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator*=(std::pair<Lhs, Rhs>&, const std::pair<Lhs, Rhs>&);
|
||||
|
||||
template <typename Lhs, typename Rhs, typename ArithT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<ArithT>>::value, int> = 0>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator*=(std::pair<Lhs, Rhs>&, const ArithT&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... _Extra>
|
||||
std::vector<Tp, _Extra...>&
|
||||
operator*=(std::vector<Tp, _Extra...>&, const std::vector<Tp, _Extra...>&);
|
||||
|
||||
template <typename Lhs, typename Rhs, typename... _Extra,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::vector<Lhs, _Extra...>&
|
||||
operator*=(std::vector<Lhs, _Extra...>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator*=(std::tuple<Types...>&, const std::tuple<Types...>&);
|
||||
|
||||
template <typename... Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::tuple<Lhs...>&
|
||||
operator*=(std::tuple<Lhs...>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator /=
|
||||
// operator /
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator/=(std::array<Tp, N>&, const std::array<Tp, N>&);
|
||||
|
||||
template <typename Lhs, size_t N, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::array<Lhs, N>&
|
||||
operator/=(std::array<Lhs, N>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator/=(std::pair<Lhs, Rhs>&, const std::pair<Lhs, Rhs>&);
|
||||
|
||||
template <typename Lhs, typename Rhs, typename ArithT,
|
||||
enable_if_t<std::is_arithmetic<decay_t<ArithT>>::value, int> = 0>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator/=(std::pair<Lhs, Rhs>&, const ArithT&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... _Extra>
|
||||
std::vector<Tp, _Extra...>&
|
||||
operator/=(std::vector<Tp, _Extra...>&, const std::vector<Tp, _Extra...>&);
|
||||
|
||||
template <typename Lhs, typename Rhs, typename... _Extra,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::vector<Lhs, _Extra...>&
|
||||
operator/=(std::vector<Lhs, _Extra...>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator/=(std::tuple<Types...>&, const std::tuple<Types...>&);
|
||||
|
||||
template <typename... Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
std::tuple<Lhs...>&
|
||||
operator/=(std::tuple<Lhs...>&, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator * (fundamental)
|
||||
// operator / (fundamental)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
Lhs operator*(Lhs, const Rhs&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs,
|
||||
enable_if_t<std::is_arithmetic<decay_t<Rhs>>::value, int> = 0>
|
||||
Lhs
|
||||
operator/(Lhs, const Rhs&);
|
||||
|
||||
} // namespace stl
|
||||
|
||||
} // namespace tim
|
||||
@@ -1,647 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#if __cplusplus >= 201703L // C++17
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_IMPL_IS_CONCEPT(CONCEPT) \
|
||||
struct CONCEPT \
|
||||
{}; \
|
||||
template <typename Tp> \
|
||||
struct is_##CONCEPT \
|
||||
{ \
|
||||
private: \
|
||||
template <typename, typename = std::true_type> \
|
||||
struct have : std::false_type \
|
||||
{}; \
|
||||
template <typename U> \
|
||||
struct have<U, typename std::is_base_of<typename U::CONCEPT, U>::type> \
|
||||
: std::true_type \
|
||||
{}; \
|
||||
template <typename U> \
|
||||
struct have<U, typename std::is_base_of<typename U::CONCEPT##_type, U>::type> \
|
||||
: std::true_type \
|
||||
{}; \
|
||||
\
|
||||
public: \
|
||||
using type = typename is_##CONCEPT::template have< \
|
||||
typename std::remove_cv<Tp>::type>::type; \
|
||||
static constexpr bool value = \
|
||||
is_##CONCEPT::template have<typename std::remove_cv<Tp>::type>::value; \
|
||||
};
|
||||
// constexpr operator bool() const noexcept { return value; }
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
class OutputArchiveBase;
|
||||
class InputArchiveBase;
|
||||
//
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
//
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
using true_type = std::true_type;
|
||||
using false_type = std::false_type;
|
||||
//
|
||||
struct null_type;
|
||||
//
|
||||
struct quirk_type;
|
||||
//
|
||||
namespace audit
|
||||
{
|
||||
struct incoming;
|
||||
struct outgoing;
|
||||
} // namespace audit
|
||||
//
|
||||
namespace trait
|
||||
{
|
||||
template <typename Tp>
|
||||
struct is_available;
|
||||
//
|
||||
template <typename Tp>
|
||||
struct is_component;
|
||||
} // namespace trait
|
||||
//
|
||||
namespace
|
||||
{
|
||||
template <typename Tp>
|
||||
struct anonymous
|
||||
{
|
||||
using type = Tp;
|
||||
};
|
||||
//
|
||||
template <typename Tp>
|
||||
using anonymous_t = typename anonymous<Tp>::type;
|
||||
} // namespace
|
||||
//
|
||||
namespace component
|
||||
{
|
||||
template <size_t Idx, typename Tag>
|
||||
struct user_bundle;
|
||||
//
|
||||
template <size_t Nt, typename ComponentsT, typename DifferentiatorT = anonymous_t<void>>
|
||||
struct gotcha;
|
||||
//
|
||||
template <typename... Types>
|
||||
struct placeholder;
|
||||
//
|
||||
struct nothing;
|
||||
//
|
||||
} // namespace component
|
||||
//
|
||||
template <typename... Types>
|
||||
class lightweight_tuple;
|
||||
//
|
||||
namespace concepts
|
||||
{
|
||||
//
|
||||
using input_archive_base = cereal::detail::InputArchiveBase;
|
||||
using output_archive_base = cereal::detail::OutputArchiveBase;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_empty
|
||||
/// \brief concept that specifies that a variadic type is empty
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(empty)
|
||||
|
||||
template <template <typename...> class Tuple>
|
||||
struct is_empty<Tuple<>> : true_type
|
||||
{};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_null_type
|
||||
/// \brief concept that specifies that a type is not a useful type
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(null_type)
|
||||
|
||||
template <template <typename...> class Tuple>
|
||||
struct is_null_type<Tuple<>> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_null_type<void> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_null_type<false_type> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_null_type<::tim::null_type> : true_type
|
||||
{};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_placeholder
|
||||
/// \brief concept that specifies that a type is not necessarily marked as not available
|
||||
/// but is still a dummy type
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(placeholder)
|
||||
|
||||
template <typename... Types>
|
||||
struct is_placeholder<component::placeholder<Types...>> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_placeholder<component::placeholder<component::nothing>> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_placeholder<component::nothing> : true_type
|
||||
{};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_component
|
||||
/// \brief concept that specifies that a type is a component. Components are used to
|
||||
/// perform some measurement, capability, or logging implementation. Adding this
|
||||
/// concept can be performs through inheriting from \ref tim::component::base,
|
||||
/// inheriting from tim::concepts::component, or specializing either \ref
|
||||
/// tim::concepts::is_component or \ref tim::trait::is_component (with the latter
|
||||
/// being deprecated).
|
||||
///
|
||||
struct component
|
||||
{};
|
||||
//
|
||||
template <typename Tp>
|
||||
struct is_component
|
||||
{
|
||||
private:
|
||||
/// did not inherit
|
||||
template <typename, typename = std::true_type>
|
||||
struct have : std::false_type
|
||||
{};
|
||||
|
||||
/// did inherit
|
||||
template <typename U>
|
||||
struct have<U, typename std::is_base_of<typename U::component, U>::type>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
/// this uses sfinae to see if U::is_component is provided within the type
|
||||
template <typename U>
|
||||
static constexpr decltype(U::is_component, bool{}) test(int)
|
||||
{
|
||||
return U::is_component;
|
||||
}
|
||||
|
||||
/// this checks for the (deprecated) `tim::trait::is_component` specialization
|
||||
/// and checks for inheritance
|
||||
template <typename Up>
|
||||
static constexpr bool test(long)
|
||||
{
|
||||
return trait::is_component<Up>::value ||
|
||||
is_component::template have<std::remove_cv_t<Tp>>::value;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr bool value = test<Tp>(int{});
|
||||
using type = std::conditional_t<value, true_type, false_type>;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_quirk_type
|
||||
/// \brief concept that specifies that a type is a quirk. Quirks are used to modify
|
||||
/// the traditional behavior of component bundles slightly. E.g. disable calling
|
||||
/// start in the constructor of an auto_tuple.
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(quirk_type)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_api
|
||||
/// \brief concept that specifies that a type is an API. APIs are used to designate
|
||||
/// different project implementations, different external library tools, etc.
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(api)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_variadic
|
||||
/// \brief concept that specifies that a type is a generic variadic wrapper
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(variadic)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_wrapper
|
||||
/// \brief concept that specifies that a type is a timemory variadic wrapper
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_stack_wrapper
|
||||
/// \brief concept that specifies that a type is a timemory variadic wrapper
|
||||
/// and components are stack-allocated
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(stack_wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_heap_wrapper
|
||||
/// \brief concept that specifies that a type is a timemory variadic wrapper
|
||||
/// and components are heap-allocated
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(heap_wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_mixed_wrapper
|
||||
/// \brief concept that specifies that a type is a timemory variadic wrapper
|
||||
/// and variadic types are mix of stack- and heap- allocated
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(mixed_wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_tagged
|
||||
/// \brief concept that specifies that a type's template parameters include
|
||||
/// a API specific tag as one of the template parameters (usually first)
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(tagged)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_comp_wrapper
|
||||
/// \brief concept that specifies that a type is a timemory variadic wrapper
|
||||
/// that does not perform auto start/stop, e.g. component_{tuple,list,hybrid}
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(comp_wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_auto_wrapper
|
||||
/// \brief concept that specifies that a type is a timemory variadic wrapper
|
||||
/// that performs auto start/stop, e.g. auto_{tuple,list,hybrid}
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(auto_wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_runtime_configurable
|
||||
/// \brief concept that specifies that a type is used to modify behavior at runtime.
|
||||
/// For example, the \ref tim::component::user_bundle component is runtime configurable bc
|
||||
/// it allows you insert components at runtime. The timing category
|
||||
/// (`tim::category::timing`) is another example of a type that is runtime configurable --
|
||||
/// setting `tim::trait::runtime_enabled<tim::category::timing>::set(false);` will disable
|
||||
/// (at runtime) all the types which are part of the timing API. It should be noted that
|
||||
/// types which satisfy `is_runtime_configurable<Tp>::value == true` (e.g. \ref
|
||||
/// tim::component::user_bundle) are not eligible to be inserted into other runtime
|
||||
/// configurable components; i.e. you cannot insert/add \ref
|
||||
/// tim::component::user_trace_bundle into \ref tim::component::user_global_bundle, etc.
|
||||
/// This restriction is primarily due to the significant increase in compile-time that
|
||||
/// arises from allowing this behavior.
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(runtime_configurable)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_external_function_wrapper
|
||||
/// \brief concept that specifies that a component type wraps external functions
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(external_function_wrapper)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_phase_id
|
||||
/// \brief concept that specifies that a type is used for identifying a phase in some
|
||||
/// measurement. For example, `tim::audit::incoming` and `tim::audit::outgoing`
|
||||
/// can be added to overloads to distinguish whether the `double` type in `double
|
||||
/// exp(double val)` is `val` or whether it is the return value.
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// struct exp_wrapper_A
|
||||
/// {
|
||||
/// // unable to distingush whether "val" is input or output
|
||||
/// void audit(double val) { ... }
|
||||
/// };
|
||||
///
|
||||
/// struct exp_wrapper_B
|
||||
/// {
|
||||
/// // able to distingush whether "val" is input or output
|
||||
/// void audit(audit::incoming, double val) { ... }
|
||||
/// void audit(audit::outgoing, double val) { ... }
|
||||
/// };
|
||||
/// \endcode
|
||||
TIMEMORY_IMPL_IS_CONCEPT(phase_id)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_string_type
|
||||
/// \brief concept that specifies that a component type wraps external functions
|
||||
///
|
||||
TIMEMORY_IMPL_IS_CONCEPT(string_type)
|
||||
|
||||
template <>
|
||||
struct is_string_type<std::string> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_string_type<char*> : true_type
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct is_string_type<const char*> : true_type
|
||||
{};
|
||||
|
||||
#if __cplusplus >= 201703L // C++17
|
||||
template <>
|
||||
struct is_string_type<std::string_view> : true_type
|
||||
{};
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::has_gotcha
|
||||
/// \brief determines if a variadic wrapper contains a gotcha component
|
||||
///
|
||||
template <typename T>
|
||||
struct has_gotcha : std::false_type
|
||||
{};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::has_user_bundle
|
||||
/// \brief concept that specifies that a type is a user_bundle type
|
||||
///
|
||||
template <typename T>
|
||||
struct has_user_bundle : false_type
|
||||
{};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_output_archive
|
||||
/// \brief concept that specifies that a type is an output serialization archive
|
||||
///
|
||||
template <typename Tp>
|
||||
struct is_output_archive
|
||||
{
|
||||
private:
|
||||
/// did not inherit
|
||||
template <typename, typename = std::true_type>
|
||||
struct have : std::false_type
|
||||
{};
|
||||
|
||||
/// did inherit
|
||||
template <typename U>
|
||||
struct have<U, typename std::is_base_of<output_archive_base, U>::type>
|
||||
: std::true_type
|
||||
{};
|
||||
|
||||
public:
|
||||
static constexpr bool value =
|
||||
is_output_archive::template have<std::remove_cv_t<Tp>>::value;
|
||||
using type = std::conditional_t<value, true_type, false_type>;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_input_archive
|
||||
/// \brief concept that specifies that a type is an input serialization archive
|
||||
///
|
||||
template <typename Tp>
|
||||
struct is_input_archive
|
||||
{
|
||||
private:
|
||||
/// did not inherit
|
||||
template <typename, typename = std::true_type>
|
||||
struct have : std::false_type
|
||||
{};
|
||||
|
||||
/// did inherit
|
||||
template <typename U>
|
||||
struct have<U, typename std::is_base_of<input_archive_base, U>::type> : std::true_type
|
||||
{};
|
||||
|
||||
public:
|
||||
static constexpr bool value =
|
||||
is_input_archive::template have<std::remove_cv_t<Tp>>::value;
|
||||
using type = std::conditional_t<value, true_type, false_type>;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_archive
|
||||
/// \brief concept that specifies that a type is a serialization archive (input or output)
|
||||
///
|
||||
template <typename Tp>
|
||||
struct is_archive
|
||||
{
|
||||
static constexpr bool value =
|
||||
is_input_archive<Tp>::value || is_output_archive<Tp>::value;
|
||||
using type = std::conditional_t<value, true_type, false_type>;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::is_acceptable_conversion
|
||||
/// \tparam Lhs the provided type
|
||||
/// \tparam Rhs the target type
|
||||
///
|
||||
/// \brief This concept designates that is safe to perform a `static_cast<Lhs>(rhs)`
|
||||
/// where needed. This is primarily used in the \ref tim::component::data_tracker
|
||||
/// where `data_tracker<unsigned int, ...>` might be provided another integral type,
|
||||
/// such as `int`.
|
||||
///
|
||||
template <typename Lhs, typename Rhs>
|
||||
struct is_acceptable_conversion
|
||||
{
|
||||
static constexpr bool value =
|
||||
(std::is_same<Lhs, Rhs>::value ||
|
||||
(std::is_integral<Lhs>::value && std::is_integral<Rhs>::value) ||
|
||||
(std::is_floating_point<Lhs>::value && std::is_floating_point<Rhs>::value));
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::concepts::tuple_type
|
||||
/// \brief This concept is used to express how to convert a given type into a
|
||||
/// `std::tuple`, e.g. `tim::component_tuple<T...>` to `std::tuple<T...>`. It
|
||||
/// is necessary for types like \ref tim::component_bundle where certain template
|
||||
/// parameters are tags.
|
||||
///
|
||||
template <typename T>
|
||||
struct tuple_type
|
||||
{
|
||||
using type = typename T::tuple_type;
|
||||
};
|
||||
|
||||
/// \struct tim::concepts::auto_type
|
||||
/// \brief This concept is used to express how to convert a component bundler into
|
||||
/// another component bundler which performs automatic starting upon construction.
|
||||
///
|
||||
template <typename T>
|
||||
struct auto_type
|
||||
{
|
||||
using type = typename T::auto_type;
|
||||
};
|
||||
|
||||
/// \struct tim::concepts::component_type
|
||||
/// \brief This concept is used to express how to convert a component bundler which
|
||||
/// automatically starts upon construction into a type that requires an explicit
|
||||
/// call to start.
|
||||
///
|
||||
template <typename T>
|
||||
struct component_type
|
||||
{
|
||||
using type = typename T::component_type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct component_type<std::tuple<>>
|
||||
{
|
||||
using type = lightweight_tuple<>;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace concepts
|
||||
|
||||
template <typename T>
|
||||
using is_empty_t = typename concepts::is_empty<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_variadic_t = typename concepts::is_variadic<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_wrapper_t = typename concepts::is_wrapper<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_stack_wrapper_t = typename concepts::is_stack_wrapper<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using is_heap_wrapper_t = typename concepts::is_heap_wrapper<T>::type;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace tim
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(TIMEMORY_CONCEPT_ALIAS)
|
||||
# define TIMEMORY_CONCEPT_ALIAS(ALIAS, TYPE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <typename T> \
|
||||
using ALIAS = typename TYPE<T>::type; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_CONCEPT_ALIAS(is_empty_t, is_empty)
|
||||
TIMEMORY_CONCEPT_ALIAS(is_variadic_t, is_variadic)
|
||||
TIMEMORY_CONCEPT_ALIAS(is_wrapper_t, is_wrapper)
|
||||
TIMEMORY_CONCEPT_ALIAS(is_stack_wrapper_t, is_stack_wrapper)
|
||||
TIMEMORY_CONCEPT_ALIAS(is_heap_wrapper_t, is_heap_wrapper)
|
||||
|
||||
TIMEMORY_CONCEPT_ALIAS(tuple_type_t, tuple_type)
|
||||
TIMEMORY_CONCEPT_ALIAS(auto_type_t, auto_type)
|
||||
TIMEMORY_CONCEPT_ALIAS(component_type_t, component_type)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_DEFINE_CONCRETE_CONCEPT(CONCEPT, SPECIALIZED_TYPE, VALUE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <> \
|
||||
struct CONCEPT<SPECIALIZED_TYPE> : VALUE \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_DEFINE_TEMPLATE_CONCEPT(CONCEPT, SPECIALIZED_TYPE, VALUE, TYPE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <TYPE T> \
|
||||
struct CONCEPT<SPECIALIZED_TYPE<T>> : VALUE \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_DEFINE_VARIADIC_CONCEPT(CONCEPT, SPECIALIZED_TYPE, VALUE, TYPE) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <TYPE... T> \
|
||||
struct CONCEPT<SPECIALIZED_TYPE<T...>> : VALUE \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_DEFINE_CONCRETE_CONCEPT_TYPE(CONCEPT, SPECIALIZED_TYPE, ...) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <> \
|
||||
struct CONCEPT<SPECIALIZED_TYPE> \
|
||||
{ \
|
||||
using type = __VA_ARGS__; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_DEFINE_TEMPLATE_CONCEPT_TYPE(CONCEPT, SPECIALIZED_TYPE, TYPE, ...) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <TYPE T> \
|
||||
struct CONCEPT<SPECIALIZED_TYPE<T>> \
|
||||
{ \
|
||||
using type = __VA_ARGS__; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define TIMEMORY_DEFINE_VARIADIC_CONCEPT_TYPE(CONCEPT, SPECIALIZED_TYPE, TYPE, ...) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace concepts \
|
||||
{ \
|
||||
template <TYPE... T> \
|
||||
struct CONCEPT<SPECIALIZED_TYPE<T...>> \
|
||||
{ \
|
||||
using type = __VA_ARGS__; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,371 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \file mpl/stl.hpp
|
||||
* \headerfile mpl/stl.hpp "timemory/mpl/stl.hpp"
|
||||
* Provides operators on common STL structures such as <<, +=, -=, *=, /=, +, -, *, /
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <ostream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "timemory/mpl/math.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace stl
|
||||
{
|
||||
namespace ostream
|
||||
{
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator <<
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T, typename U>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::pair<T, U>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::tuple<Types...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::vector<Tp, Extra...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, const std::array<Tp, N>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace ostream
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator +=
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N, typename Other>
|
||||
std::array<Tp, N>&
|
||||
operator+=(std::array<Tp, N>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Other>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator+=(std::pair<Lhs, Rhs>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra, typename Other>
|
||||
std::vector<Tp, Extra...>&
|
||||
operator+=(std::vector<Tp, Extra...>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types, typename Other>
|
||||
std::tuple<Types...>&
|
||||
operator+=(std::tuple<Types...>&, Other&&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator -=
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator-=(std::array<Tp, N>&, const std::array<Tp, N>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator-=(std::tuple<Types...>&, const std::tuple<Types...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator-=(std::pair<Lhs, Rhs>&, const std::pair<Lhs, Rhs>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...>&
|
||||
operator-=(std::vector<Tp, Extra...>&, const std::vector<Tp, Extra...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator *=
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator*=(std::array<Tp, N>&, const std::array<Tp, N>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator*=(std::pair<Lhs, Rhs>&, const std::pair<Lhs, Rhs>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator*=(std::tuple<Types...>&, const std::tuple<Types...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...>&
|
||||
operator*=(std::vector<Tp, Extra...>&, const std::vector<Tp, Extra...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator /=
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>&
|
||||
operator/=(std::array<Tp, N>&, const std::array<Tp, N>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>&
|
||||
operator/=(std::pair<Lhs, Rhs>&, const std::pair<Lhs, Rhs>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>&
|
||||
operator/=(std::tuple<Types...>&, const std::tuple<Types...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...>&
|
||||
operator/=(std::vector<Tp, Extra...>&, const std::vector<Tp, Extra...>&);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator +
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>
|
||||
operator+(std::array<Tp, N> lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::plus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>
|
||||
operator+(std::tuple<Types...> lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::plus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>
|
||||
operator+(std::pair<Lhs, Rhs> lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::plus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...>
|
||||
operator+(std::vector<Tp, Extra...> lhs, const std::vector<Tp, Extra...>& rhs)
|
||||
{
|
||||
math::plus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator -
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>
|
||||
operator-(std::array<Tp, N> lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>
|
||||
operator-(std::tuple<Types...> lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>
|
||||
operator-(std::pair<Lhs, Rhs> lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...>
|
||||
operator-(std::vector<Tp, Extra...> lhs, const std::vector<Tp, Extra...>& rhs)
|
||||
{
|
||||
math::minus(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator *
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N> operator*(std::array<Tp, N> lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...> operator*(std::tuple<Types...> lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs> operator*(std::pair<Lhs, Rhs> lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...> operator*(std::vector<Tp, Extra...> lhs,
|
||||
const std::vector<Tp, Extra...>& rhs)
|
||||
{
|
||||
math::multiply(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
// operator /
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, size_t N>
|
||||
std::array<Tp, N>
|
||||
operator/(std::array<Tp, N> lhs, const std::array<Tp, N>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Types>
|
||||
std::tuple<Types...>
|
||||
operator/(std::tuple<Types...> lhs, const std::tuple<Types...>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
std::pair<Lhs, Rhs>
|
||||
operator/(std::pair<Lhs, Rhs> lhs, const std::pair<Lhs, Rhs>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp, typename... Extra>
|
||||
std::vector<Tp, Extra...>
|
||||
operator/(std::vector<Tp, Extra...> lhs, const std::vector<Tp, Extra...>& rhs)
|
||||
{
|
||||
math::divide(lhs, rhs);
|
||||
return lhs;
|
||||
}
|
||||
|
||||
} // namespace stl
|
||||
|
||||
using namespace stl;
|
||||
|
||||
} // namespace tim
|
||||
|
||||
#include "timemory/mpl/bits/stl.hpp"
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,45 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
// cereal will cause some -Wclass-memaccess warnings that are quite annoying
|
||||
#if defined(__GNUC__) && (__GNUC__ > 7)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
|
||||
// define this so avoid warnings about noexcept functions throwing
|
||||
#if !defined(TIMEMORY_CEREAL_RAPIDJSON_ASSERT)
|
||||
# define TIMEMORY_CEREAL_RAPIDJSON_ASSERT(x) \
|
||||
{}
|
||||
#endif
|
||||
|
||||
// general
|
||||
#include "timemory/tpls/cereal/cereal/cereal.hpp"
|
||||
#include "timemory/tpls/cereal/cereal/macros.hpp"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 7)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
@@ -1,434 +0,0 @@
|
||||
/*! \file access.hpp
|
||||
\brief Access control and default construction */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TIMEMORY_CEREAL_ACCESS_HPP_
|
||||
#define TIMEMORY_CEREAL_ACCESS_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "timemory/tpls/cereal/cereal/details/helpers.hpp"
|
||||
#include "timemory/tpls/cereal/cereal/macros.hpp"
|
||||
#include "timemory/tpls/cereal/cereal/specialize.hpp"
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! A class that allows cereal to load smart pointers to types that have no default
|
||||
//! constructor
|
||||
/*! If your class does not have a default constructor, cereal will not be able
|
||||
to load any smart pointers to it unless you overload LoadAndConstruct
|
||||
for your class, and provide an appropriate load_and_construct method. You can also
|
||||
choose to define a member static function instead of specializing this class.
|
||||
|
||||
The specialization of LoadAndConstruct must be placed within the cereal namespace:
|
||||
|
||||
@code{.cpp}
|
||||
struct MyType
|
||||
{
|
||||
MyType( int x ); // note: no default ctor
|
||||
int myX;
|
||||
|
||||
// Define a serialize or load/save pair as you normally would
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( myX );
|
||||
}
|
||||
};
|
||||
|
||||
// Provide a specialization for LoadAndConstruct for your type
|
||||
namespace cereal
|
||||
{
|
||||
template <> struct LoadAndConstruct<MyType>
|
||||
{
|
||||
// load_and_construct will be passed the archive that you will be loading
|
||||
// from as well as a construct object which you can use as if it were the
|
||||
// constructor for your type. cereal will handle all memory management for you.
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> &
|
||||
construct )
|
||||
{
|
||||
int x;
|
||||
ar( x );
|
||||
construct( x );
|
||||
}
|
||||
|
||||
// if you require versioning, simply add a const std::uint32_t as the final
|
||||
parameter, e.g.:
|
||||
// load_and_construct( Archive & ar, cereal::construct<MyType> & construct,
|
||||
std::uint32_t const version )
|
||||
};
|
||||
} // end namespace cereal
|
||||
@endcode
|
||||
|
||||
Please note that just as in using external serialization functions, you cannot get
|
||||
access to non-public members of your class by befriending cereal::access. If you
|
||||
have the ability to modify the class you wish to serialize, it is recommended that you
|
||||
use member serialize functions and a static member load_and_construct function.
|
||||
|
||||
load_and_construct functions, regardless of whether they are static members of your
|
||||
class or whether you create one in the LoadAndConstruct specialization, have the
|
||||
following signature:
|
||||
|
||||
@code{.cpp}
|
||||
// generally Archive will be templated, but it can be specific if desired
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct );
|
||||
// with an optional last parameter specifying the version: const std::uint32_t version
|
||||
@endcode
|
||||
|
||||
Versioning behaves the same way as it does for standard serialization functions.
|
||||
|
||||
@tparam T The type to specialize for
|
||||
@ingroup Access */
|
||||
template <class T>
|
||||
struct LoadAndConstruct
|
||||
{};
|
||||
|
||||
// forward decl for construct
|
||||
//! @cond PRIVATE_NEVERDEFINED
|
||||
namespace memory_detail
|
||||
{
|
||||
template <class Ar, class T>
|
||||
struct LoadAndConstructLoadWrapper;
|
||||
}
|
||||
namespace boost_variant_detail
|
||||
{
|
||||
template <class Ar, class T>
|
||||
struct LoadAndConstructLoadWrapper;
|
||||
}
|
||||
//! @endcond
|
||||
|
||||
//! Used to construct types with no default constructor
|
||||
/*! When serializing a type that has no default constructor, cereal
|
||||
will attempt to call either the class static function load_and_construct
|
||||
or the appropriate template specialization of LoadAndConstruct. cereal
|
||||
will pass that function a reference to the archive as well as a reference
|
||||
to a construct object which should be used to perform the allocation once
|
||||
data has been appropriately loaded.
|
||||
|
||||
@code{.cpp}
|
||||
struct MyType
|
||||
{
|
||||
// note the lack of default constructor
|
||||
MyType( int xx, int yy );
|
||||
|
||||
int x, y;
|
||||
double notInConstructor;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x, y );
|
||||
ar( notInConstructor );
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct
|
||||
)
|
||||
{
|
||||
int x, y;
|
||||
ar( x, y );
|
||||
|
||||
// use construct object to initialize with loaded data
|
||||
construct( x, y );
|
||||
|
||||
// access to member variables and functions via -> operator
|
||||
ar( construct->notInConstructor );
|
||||
|
||||
// could also do the above section by:
|
||||
double z;
|
||||
ar( z );
|
||||
construct->notInConstructor = z;
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
@tparam T The class type being serialized
|
||||
*/
|
||||
template <class T>
|
||||
class construct
|
||||
{
|
||||
public:
|
||||
//! Construct and initialize the type T with the given arguments
|
||||
/*! This will forward all arguments to the underlying type T,
|
||||
calling an appropriate constructor.
|
||||
|
||||
Calling this function more than once will result in an exception
|
||||
being thrown.
|
||||
|
||||
@param args The arguments to the constructor for T
|
||||
@throw Exception If called more than once */
|
||||
template <class... Args>
|
||||
void operator()(Args&&... args);
|
||||
// implementation deferred due to reliance on cereal::access
|
||||
|
||||
//! Get a reference to the initialized underlying object
|
||||
/*! This must be called after the object has been initialized.
|
||||
|
||||
@return A reference to the initialized object
|
||||
@throw Exception If called before initialization */
|
||||
T* operator->()
|
||||
{
|
||||
if(!itsValid)
|
||||
throw Exception("Object must be initialized prior to accessing members");
|
||||
|
||||
return itsPtr;
|
||||
}
|
||||
|
||||
//! Returns a raw pointer to the initialized underlying object
|
||||
/*! This is mainly intended for use with passing an instance of
|
||||
a constructed object to cereal::base_class.
|
||||
|
||||
It is strongly recommended to avoid using this function in
|
||||
any other circumstance.
|
||||
|
||||
@return A raw pointer to the initialized type */
|
||||
T* ptr() { return operator->(); }
|
||||
|
||||
construct(construct const&) = delete;
|
||||
construct& operator=(construct const&) = delete;
|
||||
|
||||
private:
|
||||
template <class Ar, class TT>
|
||||
friend struct ::tim::cereal::memory_detail::LoadAndConstructLoadWrapper;
|
||||
template <class Ar, class TT>
|
||||
friend struct ::tim::cereal::boost_variant_detail::LoadAndConstructLoadWrapper;
|
||||
|
||||
construct(T* p)
|
||||
: itsPtr(p)
|
||||
, itsEnableSharedRestoreFunction([]() {})
|
||||
, itsValid(false)
|
||||
{}
|
||||
|
||||
construct(T* p, std::function<void()> enableSharedFunc)
|
||||
: // g++4.7 ice with default lambda to std func
|
||||
itsPtr(p)
|
||||
, itsEnableSharedRestoreFunction(std::move(enableSharedFunc))
|
||||
, itsValid(false)
|
||||
{}
|
||||
|
||||
T* itsPtr;
|
||||
std::function<void()> itsEnableSharedRestoreFunction;
|
||||
bool itsValid;
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! A class that can be made a friend to give cereal access to non public functions
|
||||
/*! If you desire non-public serialization functions within a class, cereal can only
|
||||
access these if you declare cereal::access a friend.
|
||||
|
||||
@code{.cpp}
|
||||
class MyClass
|
||||
{
|
||||
private:
|
||||
friend class cereal::access; // gives access to the private serialize
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
// some code
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
@ingroup Access */
|
||||
class access
|
||||
{
|
||||
public:
|
||||
// ####### Standard Serialization ########################################
|
||||
template <class Archive, class T>
|
||||
inline static auto member_serialize(Archive& ar, T& t)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(ar))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(ar);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save(Archive& ar, T const& t)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save_non_const(Archive& ar, T& t)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_load(Archive& ar, T& t)
|
||||
-> decltype(t.TIMEMORY_CEREAL_LOAD_FUNCTION_NAME(ar))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_LOAD_FUNCTION_NAME(ar);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save_minimal(Archive const& ar, T const& t)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save_minimal_non_const(Archive const& ar, T& t)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar);
|
||||
}
|
||||
|
||||
template <class Archive, class T, class U>
|
||||
inline static auto member_load_minimal(Archive const& ar, T& t, U&& u)
|
||||
-> decltype(t.TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u));
|
||||
}
|
||||
|
||||
// ####### Versioned Serialization #######################################
|
||||
template <class Archive, class T>
|
||||
inline static auto member_serialize(Archive& ar, T& t, std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(ar, version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(ar, version);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save(Archive& ar, T const& t, std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar, version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar, version);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save_non_const(Archive& ar, T& t, std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar, version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_FUNCTION_NAME(ar, version);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_load(Archive& ar, T& t, std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_LOAD_FUNCTION_NAME(ar, version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_LOAD_FUNCTION_NAME(ar, version);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save_minimal(Archive const& ar, T const& t,
|
||||
const std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version);
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
inline static auto member_save_minimal_non_const(Archive const& ar, T& t,
|
||||
const std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version);
|
||||
}
|
||||
|
||||
template <class Archive, class T, class U>
|
||||
inline static auto member_load_minimal(Archive const& ar, T& t, U&& u,
|
||||
const std::uint32_t version)
|
||||
-> decltype(t.TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u),
|
||||
version))
|
||||
{
|
||||
return t.TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u),
|
||||
version);
|
||||
}
|
||||
|
||||
// ####### Other Functionality ##########################################
|
||||
// for detecting inheritance from enable_shared_from_this
|
||||
template <class T>
|
||||
inline static auto shared_from_this(T& t) -> decltype(t.shared_from_this());
|
||||
|
||||
// for placement new
|
||||
template <class T, class... Args>
|
||||
inline static void construct(T*& ptr, Args&&... args)
|
||||
{
|
||||
new(ptr) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// for non-placement new with a default constructor
|
||||
template <class T>
|
||||
inline static T* construct()
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline static std::false_type load_and_construct(...)
|
||||
{
|
||||
return std::false_type();
|
||||
}
|
||||
|
||||
template <class T, class Archive>
|
||||
inline static auto load_and_construct(Archive& ar,
|
||||
::tim::cereal::construct<T>& construct)
|
||||
-> decltype(T::load_and_construct(ar, construct))
|
||||
{
|
||||
T::load_and_construct(ar, construct);
|
||||
}
|
||||
|
||||
template <class T, class Archive>
|
||||
inline static auto load_and_construct(Archive& ar,
|
||||
::tim::cereal::construct<T>& construct,
|
||||
const std::uint32_t version)
|
||||
-> decltype(T::load_and_construct(ar, construct, version))
|
||||
{
|
||||
T::load_and_construct(ar, construct, version);
|
||||
}
|
||||
}; // end class access
|
||||
|
||||
// ######################################################################
|
||||
// Deferred Implementation, see construct for more information
|
||||
template <class T>
|
||||
template <class... Args>
|
||||
inline void
|
||||
construct<T>::operator()(Args&&... args)
|
||||
{
|
||||
if(itsValid)
|
||||
throw Exception("Attempting to construct an already initialized object");
|
||||
|
||||
::tim::cereal::access::construct(itsPtr, std::forward<Args>(args)...);
|
||||
itsEnableSharedRestoreFunction();
|
||||
itsValid = true;
|
||||
}
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
#endif // TIMEMORY_CEREAL_ACCESS_HPP_
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
-467
@@ -1,467 +0,0 @@
|
||||
/*! \file helpers.hpp
|
||||
\brief Internal helper functionality
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TIMEMORY_CEREAL_DETAILS_HELPERS_HPP_
|
||||
#define TIMEMORY_CEREAL_DETAILS_HELPERS_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "timemory/tpls/cereal/cereal/details/static_object.hpp"
|
||||
#include "timemory/tpls/cereal/cereal/macros.hpp"
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! An exception class thrown when things go wrong at runtime
|
||||
/*! @ingroup Utility */
|
||||
struct Exception : public std::runtime_error
|
||||
{
|
||||
explicit Exception(const std::string& what_)
|
||||
: std::runtime_error(what_)
|
||||
{}
|
||||
explicit Exception(const char* what_)
|
||||
: std::runtime_error(what_)
|
||||
{}
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! The size type used by cereal
|
||||
/*! To ensure compatability between 32, 64, etc bit machines, we need to use
|
||||
a fixed size type instead of size_t, which may vary from machine to
|
||||
machine.
|
||||
|
||||
The default value for TIMEMORY_CEREAL_SIZE_TYPE is specified in cereal/macros.hpp */
|
||||
using size_type = TIMEMORY_CEREAL_SIZE_TYPE;
|
||||
|
||||
// forward decls
|
||||
class BinaryOutputArchive;
|
||||
class BinaryInputArchive;
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
struct NameValuePairCore
|
||||
{}; //!< Traits struct for NVPs
|
||||
struct DeferredDataCore
|
||||
{}; //!< Traits struct for DeferredData
|
||||
} // namespace detail
|
||||
|
||||
// ######################################################################
|
||||
//! For holding name value pairs
|
||||
/*! This pairs a name (some string) with some value such that an archive
|
||||
can potentially take advantage of the pairing.
|
||||
|
||||
In serialization functions, NameValuePairs are usually created like so:
|
||||
@code{.cpp}
|
||||
struct MyStruct
|
||||
{
|
||||
int a, b, c, d, e;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive( TIMEMORY_CEREAL_NVP(a),
|
||||
TIMEMORY_CEREAL_NVP(b),
|
||||
TIMEMORY_CEREAL_NVP(c),
|
||||
TIMEMORY_CEREAL_NVP(d),
|
||||
TIMEMORY_CEREAL_NVP(e) );
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
Alternatively, you can give you data members custom names like so:
|
||||
@code{.cpp}
|
||||
struct MyStruct
|
||||
{
|
||||
int a, b, my_embarrassing_variable_name, d, e;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive( TIMEMORY_CEREAL_NVP(a),
|
||||
TIMEMORY_CEREAL_NVP(b),
|
||||
cereal::make_nvp("var", my_embarrassing_variable_name) );
|
||||
TIMEMORY_CEREAL_NVP(d),
|
||||
TIMEMORY_CEREAL_NVP(e) );
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
There is a slight amount of overhead to creating NameValuePairs, so there
|
||||
is a third method which will elide the names when they are not used by
|
||||
the Archive:
|
||||
|
||||
@code{.cpp}
|
||||
struct MyStruct
|
||||
{
|
||||
int a, b;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive( cereal::make_nvp<Archive>(a),
|
||||
cereal::make_nvp<Archive>(b) );
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
This third method is generally only used when providing generic type
|
||||
support. Users writing their own serialize functions will normally
|
||||
explicitly control whether they want to use NVPs or not.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
class NameValuePair : detail::NameValuePairCore
|
||||
{
|
||||
private:
|
||||
// If we get passed an array, keep the type as is, otherwise store
|
||||
// a reference if we were passed an l value reference, else copy the value
|
||||
using Type = typename std::conditional<
|
||||
std::is_array<typename std::remove_reference<T>::type>::value,
|
||||
typename std::remove_cv<T>::type,
|
||||
typename std::conditional<std::is_lvalue_reference<T>::value, T,
|
||||
typename std::decay<T>::type>::type>::type;
|
||||
|
||||
// prevent nested nvps
|
||||
static_assert(!std::is_base_of<detail::NameValuePairCore, T>::value,
|
||||
"Cannot pair a name to a NameValuePair");
|
||||
|
||||
public:
|
||||
//! Constructs a new NameValuePair
|
||||
/*! @param n The name of the pair
|
||||
@param v The value to pair. Ideally this should be an l-value reference so that
|
||||
the value can be both loaded and saved to. If you pass an r-value
|
||||
reference, the NameValuePair will store a copy of it instead of a reference. Thus
|
||||
you should only pass r-values in cases where this makes sense, such as the result
|
||||
of some size() call.
|
||||
@internal */
|
||||
NameValuePair(char const* n, T&& v)
|
||||
: name(n)
|
||||
, value(std::forward<T>(v))
|
||||
{}
|
||||
|
||||
NameValuePair& operator=(NameValuePair const&) = delete;
|
||||
|
||||
char const* name; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
Type value; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
};
|
||||
|
||||
//! A specialization of make_nvp<> that simply forwards the value for binary archives
|
||||
/*! @relates NameValuePair
|
||||
@internal */
|
||||
template <class Archive, class T>
|
||||
inline typename std::enable_if<
|
||||
std::is_same<Archive, ::tim::cereal::BinaryInputArchive>::value ||
|
||||
std::is_same<Archive, ::tim::cereal::BinaryOutputArchive>::value,
|
||||
T&&>::type
|
||||
make_nvp(const char*, T&& value)
|
||||
{
|
||||
return std::forward<T>(value);
|
||||
}
|
||||
|
||||
//! A specialization of make_nvp<> that actually creates an nvp for non-binary archives
|
||||
/*! @relates NameValuePair
|
||||
@internal */
|
||||
template <class Archive, class T>
|
||||
inline typename std::enable_if<
|
||||
!std::is_same<Archive, ::tim::cereal::BinaryInputArchive>::value &&
|
||||
!std::is_same<Archive, ::tim::cereal::BinaryOutputArchive>::value,
|
||||
NameValuePair<T>>::type
|
||||
make_nvp(const char* name, T&& value)
|
||||
{
|
||||
return { name, std::forward<T>(value) };
|
||||
}
|
||||
|
||||
//! Convenience for creating a templated NVP
|
||||
/*! For use in internal generic typing functions which have an
|
||||
Archive type declared
|
||||
@internal */
|
||||
#define TIMEMORY_CEREAL_NVP_(name, value) ::tim::cereal::make_nvp<Archive>(name, value)
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around data that can be serialized in a binary fashion
|
||||
/*! This class is used to demarcate data that can safely be serialized
|
||||
as a binary chunk of data. Individual archives can then choose how
|
||||
best represent this during serialization.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
struct BinaryData
|
||||
{
|
||||
//! Internally store the pointer as a void *, keeping const if created with
|
||||
//! a const pointer
|
||||
using PT = typename std::conditional<
|
||||
std::is_const<typename std::remove_pointer<
|
||||
typename std::remove_reference<T>::type>::type>::value,
|
||||
const void*, void*>::type;
|
||||
|
||||
BinaryData(T&& d, uint64_t s)
|
||||
: data(std::forward<T>(d))
|
||||
, size(s)
|
||||
{}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
PT data; //!< pointer to beginning of data
|
||||
// NOLINTNEXTLINE
|
||||
uint64_t size; //!< size in bytes
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around data that should be serialized after all non-deferred data
|
||||
/*! This class is used to demarcate data that can only be safely serialized after
|
||||
any data not wrapped in this class.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
class DeferredData : detail::DeferredDataCore
|
||||
{
|
||||
private:
|
||||
// If we get passed an array, keep the type as is, otherwise store
|
||||
// a reference if we were passed an l value reference, else copy the value
|
||||
using Type = typename std::conditional<
|
||||
std::is_array<typename std::remove_reference<T>::type>::value,
|
||||
typename std::remove_cv<T>::type,
|
||||
typename std::conditional<std::is_lvalue_reference<T>::value, T,
|
||||
typename std::decay<T>::type>::type>::type;
|
||||
|
||||
// prevent nested nvps
|
||||
static_assert(!std::is_base_of<detail::DeferredDataCore, T>::value,
|
||||
"Cannot defer DeferredData");
|
||||
|
||||
public:
|
||||
//! Constructs a new NameValuePair
|
||||
/*! @param v The value to defer. Ideally this should be an l-value reference so that
|
||||
the value can be both loaded and saved to. If you pass an r-value
|
||||
reference, the DeferredData will store a copy of it instead of a reference. Thus
|
||||
you should only pass r-values in cases where this makes sense, such as the result
|
||||
of some size() call.
|
||||
@internal */
|
||||
DeferredData(T&& v)
|
||||
: value(std::forward<T>(v))
|
||||
{}
|
||||
|
||||
DeferredData& operator=(DeferredData const&) = delete;
|
||||
|
||||
Type value; // NOLINT
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
// base classes for type checking
|
||||
/* The rtti virtual function only exists to enable an archive to
|
||||
be used in a polymorphic fashion, if necessary. See the
|
||||
archive adapters for an example of this */
|
||||
class OutputArchiveBase
|
||||
{
|
||||
public:
|
||||
OutputArchiveBase() = default;
|
||||
OutputArchiveBase(OutputArchiveBase&&) TIMEMORY_CEREAL_NOEXCEPT {}
|
||||
OutputArchiveBase& operator=(OutputArchiveBase&&) TIMEMORY_CEREAL_NOEXCEPT
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
virtual ~OutputArchiveBase() TIMEMORY_CEREAL_NOEXCEPT = default;
|
||||
|
||||
private:
|
||||
virtual void rtti() {}
|
||||
};
|
||||
|
||||
class InputArchiveBase
|
||||
{
|
||||
public:
|
||||
InputArchiveBase() = default;
|
||||
InputArchiveBase(InputArchiveBase&&) TIMEMORY_CEREAL_NOEXCEPT {}
|
||||
InputArchiveBase& operator=(InputArchiveBase&&) TIMEMORY_CEREAL_NOEXCEPT
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
virtual ~InputArchiveBase() TIMEMORY_CEREAL_NOEXCEPT = default;
|
||||
|
||||
private:
|
||||
virtual void rtti() {}
|
||||
};
|
||||
|
||||
// forward decls for polymorphic support
|
||||
template <class Archive, class T>
|
||||
struct polymorphic_serialization_support;
|
||||
struct adl_tag;
|
||||
|
||||
// used during saving pointers
|
||||
static const uint32_t msb_32bit = 0x80000000;
|
||||
static const int32_t msb2_32bit = 0x40000000;
|
||||
} // namespace detail
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around size metadata
|
||||
/*! This class provides a way for archives to have more flexibility over how
|
||||
they choose to serialize size metadata for containers. For some archive
|
||||
types, the size may be implicitly encoded in the output (e.g. JSON) and
|
||||
not need an explicit entry. Specializing serialize or load/save for
|
||||
your archive and SizeTags allows you to choose what happens.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
class SizeTag
|
||||
{
|
||||
private:
|
||||
// Store a reference if passed an lvalue reference, otherwise
|
||||
// make a copy of the data
|
||||
using Type = typename std::conditional<std::is_lvalue_reference<T>::value, T,
|
||||
typename std::decay<T>::type>::type;
|
||||
|
||||
public:
|
||||
SizeTag(T&& sz)
|
||||
: size(std::forward<T>(sz))
|
||||
{}
|
||||
|
||||
SizeTag& operator=(SizeTag const&) = delete;
|
||||
|
||||
Type size; // NOLINT
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around a key and value for serializing data into maps.
|
||||
/*! This class just provides a grouping of keys and values into a struct for
|
||||
human readable archives. For example, XML archives will use this wrapper
|
||||
to write maps like so:
|
||||
|
||||
@code{.xml}
|
||||
<mymap>
|
||||
<item0>
|
||||
<key>MyFirstKey</key>
|
||||
<value>MyFirstValue</value>
|
||||
</item0>
|
||||
<item1>
|
||||
<key>MySecondKey</key>
|
||||
<value>MySecondValue</value>
|
||||
</item1>
|
||||
</mymap>
|
||||
@endcode
|
||||
|
||||
\sa make_map_item
|
||||
@internal */
|
||||
template <class Key, class Value>
|
||||
struct MapItem
|
||||
{
|
||||
using KeyType = typename std::conditional<std::is_lvalue_reference<Key>::value, Key,
|
||||
typename std::decay<Key>::type>::type;
|
||||
|
||||
using ValueType =
|
||||
typename std::conditional<std::is_lvalue_reference<Value>::value, Value,
|
||||
typename std::decay<Value>::type>::type;
|
||||
|
||||
//! Construct a MapItem from a key and a value
|
||||
/*! @internal */
|
||||
MapItem(Key&& key_, Value&& value_)
|
||||
: key(std::forward<Key>(key_))
|
||||
, value(std::forward<Value>(value_))
|
||||
{}
|
||||
|
||||
MapItem& operator=(MapItem const&) = delete;
|
||||
|
||||
KeyType key; // NOLINT
|
||||
ValueType value; // NOLINT
|
||||
|
||||
//! Serialize the MapItem with the NVPs "key" and "value"
|
||||
template <class Archive>
|
||||
inline void TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(Archive& archive)
|
||||
{
|
||||
archive(make_nvp<Archive>("key", key), make_nvp<Archive>("value", value));
|
||||
}
|
||||
};
|
||||
|
||||
//! Create a MapItem so that human readable archives will group keys and values together
|
||||
/*! @internal
|
||||
@relates MapItem */
|
||||
template <class KeyType, class ValueType>
|
||||
inline MapItem<KeyType, ValueType>
|
||||
make_map_item(KeyType&& key, ValueType&& value)
|
||||
{
|
||||
return { std::forward<KeyType>(key), std::forward<ValueType>(value) };
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//! Tag for Version, which due to its anonymous namespace, becomes a different
|
||||
//! type in each translation unit
|
||||
/*! This allows TIMEMORY_CEREAL_CLASS_VERSION to be safely called in a header file */
|
||||
namespace
|
||||
{
|
||||
struct version_binding_tag
|
||||
{};
|
||||
} // namespace
|
||||
|
||||
// ######################################################################
|
||||
//! Static Version information class
|
||||
/*! This is the base case for classes that have not been explicitly
|
||||
registered */
|
||||
template <class T>
|
||||
struct StaticVersion
|
||||
{
|
||||
static constexpr std::uint32_t version = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
// ######################################################################
|
||||
/// Version information class
|
||||
/// This is the base case for classes that have not been explicitly
|
||||
/// registered
|
||||
template <class T, class BindingTag = version_binding_tag>
|
||||
struct Version
|
||||
{
|
||||
static const std::uint32_t version = 0;
|
||||
// we don't need to explicitly register these types since they
|
||||
// always get a version number of 0
|
||||
};
|
||||
|
||||
/// Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
|
||||
std::uint32_t find(std::size_t hash, std::uint32_t version)
|
||||
{
|
||||
const auto result = mapping.emplace(hash, version);
|
||||
return result.first->second;
|
||||
}
|
||||
}; // struct Versions
|
||||
*/
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
#endif // TIMEMORY_CEREAL_DETAILS_HELPERS_HPP_
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*! \file polymorphic_impl_fwd.hpp
|
||||
\brief Internal polymorphism support forward declarations
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This code is heavily inspired by the boost serialization implementation by the
|
||||
following authors
|
||||
|
||||
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
(C) Copyright 2006 David Abrahams - http://www.boost.org.
|
||||
|
||||
See /boost/serialization/export.hpp and /boost/archive/detail/register_archive.hpp for
|
||||
their implementation.
|
||||
*/
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_DETAILS_POLYMORPHIC_IMPL_FWD_HPP_
|
||||
#define TIMEMORY_CEREAL_DETAILS_POLYMORPHIC_IMPL_FWD_HPP_
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
//! Forward declaration, see polymorphic_impl.hpp for more information
|
||||
template <class Base, class Derived>
|
||||
struct RegisterPolymorphicCaster;
|
||||
|
||||
//! Forward declaration, see polymorphic_impl.hpp for more information
|
||||
struct PolymorphicCasters;
|
||||
|
||||
//! Forward declaration, see polymorphic_impl.hpp for more information
|
||||
template <class Base, class Derived>
|
||||
struct PolymorphicRelation;
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
#endif // TIMEMORY_CEREAL_DETAILS_POLYMORPHIC_IMPL_FWD_HPP_
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
/*! \file static_object.hpp
|
||||
\brief Internal polymorphism static object support
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TIMEMORY_CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
#define TIMEMORY_CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
|
||||
#include "timemory/tpls/cereal/cereal/macros.hpp"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
//! Prevent link optimization from removing non-referenced static objects
|
||||
/*! Especially for polymorphic support, we create static objects which
|
||||
may not ever be explicitly referenced. Most linkers will detect this
|
||||
and remove the code causing various unpleasant runtime errors. These
|
||||
macros, adopted from Boost (see force_include.hpp) prevent this
|
||||
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt) */
|
||||
|
||||
#if !defined(TIMEMORY_CEREAL_DLL_EXPORT)
|
||||
# ifdef _MSC_VER
|
||||
# define TIMEMORY_CEREAL_DLL_EXPORT __declspec(dllexport)
|
||||
# else // clang or gcc
|
||||
# define TIMEMORY_CEREAL_DLL_EXPORT __attribute__((visibility("default")))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_CEREAL_USED)
|
||||
# ifdef _MSC_VER
|
||||
# define TIMEMORY_CEREAL_USED
|
||||
# else // clang or gcc
|
||||
# define TIMEMORY_CEREAL_USED __attribute__((__used__))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
//! A static, pre-execution object
|
||||
/*! This class will create a single copy (singleton) of some
|
||||
type and ensures that merely referencing this type will
|
||||
cause it to be instantiated and initialized pre-execution.
|
||||
For example, this is used heavily in the polymorphic pointer
|
||||
serialization mechanisms to bind various archive types with
|
||||
different polymorphic classes */
|
||||
template <class T>
|
||||
class TIMEMORY_CEREAL_DLL_EXPORT StaticObject
|
||||
{
|
||||
private:
|
||||
static T& create()
|
||||
{
|
||||
static T t;
|
||||
//! Forces instantiation at pre-execution time
|
||||
(void) instance;
|
||||
return t;
|
||||
}
|
||||
|
||||
StaticObject(StaticObject const& /*other*/) = default;
|
||||
|
||||
public:
|
||||
static T& getInstance() { return create(); }
|
||||
|
||||
//! A class that acts like std::lock_guard
|
||||
class LockGuard
|
||||
{
|
||||
public:
|
||||
LockGuard(std::mutex& m)
|
||||
: lock(m)
|
||||
{}
|
||||
|
||||
private:
|
||||
std::unique_lock<std::mutex> lock;
|
||||
};
|
||||
|
||||
//! Attempts to lock this static object for the current scope
|
||||
/*!
|
||||
This function returns an object that holds a lock for
|
||||
this StaticObject that will release its lock upon destruction. This
|
||||
call will block until the lock is available. */
|
||||
static LockGuard lock()
|
||||
{
|
||||
static std::mutex instanceMutex;
|
||||
return LockGuard{ instanceMutex };
|
||||
}
|
||||
|
||||
private:
|
||||
static T& instance;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T& StaticObject<T>::instance = StaticObject<T>::create();
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
#endif // TIMEMORY_CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
-1765
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,143 +0,0 @@
|
||||
/*! \file macros.hpp
|
||||
\brief Preprocessor macros that can customise the cereal library
|
||||
|
||||
By default, cereal looks for serialization functions with very
|
||||
specific names, that is: serialize, load, save, load_minimal,
|
||||
or save_minimal.
|
||||
|
||||
This file allows an advanced user to change these names to conform
|
||||
to some other style or preference. This is implemented using
|
||||
preprocessor macros.
|
||||
|
||||
As a result of this, in internal cereal code you will see macros
|
||||
used for these function names. In user code, you should name
|
||||
the functions like you normally would and not use the macros
|
||||
to improve readability.
|
||||
\ingroup utility */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_MACROS_HPP_
|
||||
#define TIMEMORY_CEREAL_MACROS_HPP_
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_SIZE_TYPE
|
||||
//! Determines the data type used for size_type
|
||||
/*! cereal uses size_type to ensure that the serialized size of
|
||||
dynamic containers is compatible across different architectures
|
||||
(e.g. 32 vs 64 bit), which may use different underlying types for
|
||||
std::size_t.
|
||||
|
||||
More information can be found in cereal/details/helpers.hpp.
|
||||
|
||||
If you choose to modify this type, ensure that you use a fixed
|
||||
size type (e.g. uint32_t). */
|
||||
# define TIMEMORY_CEREAL_SIZE_TYPE uint64_t
|
||||
#endif // TIMEMORY_CEREAL_SIZE_TYPE
|
||||
|
||||
// ######################################################################
|
||||
#ifndef TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME
|
||||
//! The serialization/deserialization function name to search for.
|
||||
/*! You can define @c TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME to be different assuming
|
||||
you do so before this file is included. */
|
||||
# define TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME serialize
|
||||
#endif // TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_LOAD_FUNCTION_NAME
|
||||
//! The deserialization (load) function name to search for.
|
||||
/*! You can define @c TIMEMORY_CEREAL_LOAD_FUNCTION_NAME to be different assuming you do
|
||||
so before this file is included. */
|
||||
# define TIMEMORY_CEREAL_LOAD_FUNCTION_NAME load
|
||||
#endif // TIMEMORY_CEREAL_LOAD_FUNCTION_NAME
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_SAVE_FUNCTION_NAME
|
||||
//! The serialization (save) function name to search for.
|
||||
/*! You can define @c TIMEMORY_CEREAL_SAVE_FUNCTION_NAME to be different assuming you do
|
||||
so before this file is included. */
|
||||
# define TIMEMORY_CEREAL_SAVE_FUNCTION_NAME save
|
||||
#endif // TIMEMORY_CEREAL_SAVE_FUNCTION_NAME
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME
|
||||
//! The deserialization (load_minimal) function name to search for.
|
||||
/*! You can define @c TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME to be different assuming
|
||||
you do so before this file is included. */
|
||||
# define TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME load_minimal
|
||||
#endif // TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME
|
||||
//! The serialization (save_minimal) function name to search for.
|
||||
/*! You can define @c TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME to be different assuming
|
||||
you do so before this file is included. */
|
||||
# define TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME save_minimal
|
||||
#endif // TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME
|
||||
|
||||
// ######################################################################
|
||||
//! Defines the TIMEMORY_CEREAL_NOEXCEPT macro to use instead of noexcept
|
||||
/*! If a compiler we support does not support noexcept, this macro
|
||||
will detect this and define TIMEMORY_CEREAL_NOEXCEPT as a no-op
|
||||
@internal */
|
||||
#if !defined(TIMEMORY_CEREAL_HAS_NOEXCEPT)
|
||||
# if defined(__clang__)
|
||||
# if __has_feature(cxx_noexcept)
|
||||
# define TIMEMORY_CEREAL_HAS_NOEXCEPT
|
||||
# endif
|
||||
# else // NOT clang
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
|
||||
__GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
|
||||
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
|
||||
# define TIMEMORY_CEREAL_HAS_NOEXCEPT
|
||||
# endif // end GCC/MSVC check
|
||||
# endif // end NOT clang block
|
||||
|
||||
# ifndef TIMEMORY_CEREAL_NOEXCEPT
|
||||
# ifdef TIMEMORY_CEREAL_HAS_NOEXCEPT
|
||||
# define TIMEMORY_CEREAL_NOEXCEPT noexcept
|
||||
# else
|
||||
# define TIMEMORY_CEREAL_NOEXCEPT
|
||||
# endif // end TIMEMORY_CEREAL_HAS_NOEXCEPT
|
||||
# endif // end !defined(TIMEMORY_CEREAL_HAS_NOEXCEPT)
|
||||
#endif // ifndef TIMEMORY_CEREAL_NOEXCEPT
|
||||
|
||||
// ######################################################################
|
||||
//! Checks if C++17 is available
|
||||
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
# define TIMEMORY_CEREAL_HAS_CPP17
|
||||
#endif
|
||||
|
||||
//! Checks if C++14 is available
|
||||
#if __cplusplus >= 201402L
|
||||
# define TIMEMORY_CEREAL_HAS_CPP14
|
||||
#endif
|
||||
|
||||
// ######################################################################
|
||||
//! Defines the TIMEMORY_CEREAL_ALIGNOF macro to use instead of alignof
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
# define TIMEMORY_CEREAL_ALIGNOF __alignof
|
||||
#else // not MSVC 2013 or older
|
||||
# define TIMEMORY_CEREAL_ALIGNOF alignof
|
||||
#endif // end MSVC check
|
||||
|
||||
#endif // TIMEMORY_CEREAL_MACROS_HPP_
|
||||
@@ -1,168 +0,0 @@
|
||||
/*! \file specialize.hpp
|
||||
\brief Serialization disambiguation */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TIMEMORY_CEREAL_SPECIALIZE_HPP_
|
||||
#define TIMEMORY_CEREAL_SPECIALIZE_HPP_
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
// Forward declaration of access class that users can become friends with
|
||||
class access;
|
||||
|
||||
// ######################################################################
|
||||
//! A specifier used in conjunction with cereal::specialize to disambiguate
|
||||
//! serialization in special cases
|
||||
/*! @relates specialize
|
||||
@ingroup Access */
|
||||
enum class specialization
|
||||
{
|
||||
member_serialize, //!< Force the use of a member serialize function
|
||||
member_load_save, //!< Force the use of a member load/save pair
|
||||
member_load_save_minimal, //!< Force the use of a member minimal load/save pair
|
||||
non_member_serialize, //!< Force the use of a non-member serialize function
|
||||
non_member_load_save, //!< Force the use of a non-member load/save pair
|
||||
non_member_load_save_minimal //!< Force the use of a non-member minimal load/save
|
||||
//!< pair
|
||||
};
|
||||
|
||||
//! A class used to disambiguate cases where cereal cannot detect a unique way of
|
||||
//! serializing a class
|
||||
/*! cereal attempts to figure out which method of serialization (member vs. non-member
|
||||
serialize or load/save pair) at compile time. If for some reason cereal cannot find a
|
||||
non-ambiguous way of serializing a type, it will produce a static assertion complaining
|
||||
about this.
|
||||
|
||||
This can happen because you have both a serialize and load/save pair, or even because
|
||||
a base class has a serialize (public or private with friend access) and a derived class
|
||||
does not overwrite this due to choosing some other serialization type.
|
||||
|
||||
Specializing this class will tell cereal to explicitly use the serialization type you
|
||||
specify and it will not complain about ambiguity in its compile time selection.
|
||||
However, if cereal detects an ambiguity in specializations, it will continue to issue a
|
||||
static assertion.
|
||||
|
||||
@code{.cpp}
|
||||
class MyParent
|
||||
{
|
||||
friend class cereal::access;
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar ) {}
|
||||
};
|
||||
|
||||
// Although serialize is private in MyParent, to cereal::access it will look public,
|
||||
// even through MyDerived
|
||||
class MyDerived : public MyParent
|
||||
{
|
||||
public:
|
||||
template <class Archive>
|
||||
void load( Archive & ar ) {}
|
||||
|
||||
template <class Archive>
|
||||
void save( Archive & ar ) {}
|
||||
};
|
||||
|
||||
// The load/save pair in MyDerived is ambiguous because serialize in MyParent can
|
||||
// be accessed from cereal::access. This looks the same as making serialize public
|
||||
// in MyParent, making it seem as though MyDerived has both a serialize and a
|
||||
load/save pair.
|
||||
// cereal will complain about this at compile time unless we disambiguate:
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// This struct specialization will tell cereal which is the right way to serialize
|
||||
the ambiguity template <class Archive> struct specialize<Archive, MyDerived,
|
||||
cereal::specialization::member_load_save> {};
|
||||
|
||||
// If we only had a disambiguation for a specific archive type, it would look
|
||||
something like this template <> struct specialize<cereal::BinaryOutputArchive,
|
||||
MyDerived, cereal::specialization::member_load_save> {};
|
||||
}
|
||||
@endcode
|
||||
|
||||
You can also choose to use the macros TIMEMORY_CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES or
|
||||
TIMEMORY_CEREAL_SPECIALIZE_FOR_ARCHIVE if you want to type a little bit less.
|
||||
|
||||
@tparam T The type to specialize the serialization for
|
||||
@tparam S The specialization type to use for T
|
||||
@ingroup Access */
|
||||
template <class Archive, class T, specialization S>
|
||||
struct specialize : public std::false_type
|
||||
{};
|
||||
|
||||
//! Convenient macro for performing specialization for all archive types
|
||||
/*! This performs specialization for the specific type for all types of archives.
|
||||
This macro should be placed at the global namespace.
|
||||
|
||||
@code{cpp}
|
||||
struct MyType {};
|
||||
TIMEMORY_CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( MyType,
|
||||
cereal::specialization::member_load_save
|
||||
);
|
||||
@endcode
|
||||
|
||||
@relates specialize
|
||||
@ingroup Access */
|
||||
#define TIMEMORY_CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES(Type, Specialization) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace cereal \
|
||||
{ \
|
||||
template <class Archive> \
|
||||
struct specialize<Archive, Type, Specialization> \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
|
||||
//! Convenient macro for performing specialization for a single archive type
|
||||
/*! This performs specialization for the specific type for a single type of archive.
|
||||
This macro should be placed at the global namespace.
|
||||
|
||||
@code{cpp}
|
||||
struct MyType {};
|
||||
TIMEMORY_CEREAL_SPECIALIZE_FOR_ARCHIVE( cereal::XMLInputArchive, MyType,
|
||||
cereal::specialization::member_load_save );
|
||||
@endcode
|
||||
|
||||
@relates specialize
|
||||
@ingroup Access */
|
||||
#define TIMEMORY_CEREAL_SPECIALIZE_FOR_ARCHIVE(Archive, Type, Specialization) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace cereal \
|
||||
{ \
|
||||
template <> \
|
||||
struct specialize<Archive, Type, Specialization> \
|
||||
{}; \
|
||||
} \
|
||||
}
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
#endif
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
/*! \file base_class.hpp
|
||||
\brief Support for base classes (virtual and non-virtual)
|
||||
\ingroup OtherTypes */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TIMEMORY_CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
#define TIMEMORY_CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
|
||||
#include "timemory/tpls/cereal/cereal/details/polymorphic_impl_fwd.hpp"
|
||||
#include "timemory/tpls/cereal/cereal/details/traits.hpp"
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
namespace base_class_detail
|
||||
{
|
||||
//! Used to register polymorphic relations and avoid the need to include
|
||||
//! polymorphic.hpp when no polymorphism is used
|
||||
/*! @internal */
|
||||
template <class Base, class Derived,
|
||||
bool IsPolymorphic = std::is_polymorphic<Base>::value>
|
||||
struct RegisterPolymorphicBaseClass
|
||||
{
|
||||
static void bind() {}
|
||||
};
|
||||
|
||||
//! Polymorphic version
|
||||
/*! @internal */
|
||||
template <class Base, class Derived>
|
||||
struct RegisterPolymorphicBaseClass<Base, Derived, true>
|
||||
{
|
||||
static void bind() { detail::RegisterPolymorphicCaster<Base, Derived>::bind(); }
|
||||
};
|
||||
} // namespace base_class_detail
|
||||
|
||||
//! Casts a derived class to its non-virtual base class in a way that safely supports
|
||||
//! abstract classes
|
||||
/*! This should be used in cases when a derived type needs to serialize its base type.
|
||||
This is better than directly using static_cast, as it allows for serialization of pure
|
||||
virtual (abstract) base classes.
|
||||
|
||||
This also automatically registers polymorphic relation between the base and derived
|
||||
class, assuming they are indeed polymorphic. Note this is not the same as polymorphic
|
||||
type registration. For more information see the documentation on polymorphism. If using
|
||||
a polymorphic class, be sure to include support for polymorphism
|
||||
(cereal/types/polymorphic.hpp).
|
||||
|
||||
\sa virtual_base_class
|
||||
|
||||
@code{.cpp}
|
||||
struct MyBase
|
||||
{
|
||||
int x;
|
||||
|
||||
virtual void foo() = 0;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x );
|
||||
}
|
||||
};
|
||||
|
||||
struct MyDerived : public MyBase //<-- Note non-virtual inheritance
|
||||
{
|
||||
int y;
|
||||
|
||||
virtual void foo() {};
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::base_class<MyBase>(this) );
|
||||
ar( y );
|
||||
}
|
||||
};
|
||||
@endcode */
|
||||
template <class Base>
|
||||
struct base_class : private traits::detail::BaseCastBase
|
||||
{
|
||||
template <class Derived>
|
||||
base_class(Derived const* derived)
|
||||
: base_ptr(const_cast<Base*>(static_cast<Base const*>(derived)))
|
||||
{
|
||||
static_assert(std::is_base_of<Base, Derived>::value,
|
||||
"Can only use base_class on a valid base class");
|
||||
base_class_detail::RegisterPolymorphicBaseClass<Base, Derived>::bind();
|
||||
}
|
||||
|
||||
Base* base_ptr;
|
||||
};
|
||||
|
||||
//! Casts a derived class to its virtual base class in a way that allows cereal to track
|
||||
//! inheritance
|
||||
/*! This should be used in cases when a derived type features virtual inheritance from
|
||||
some base type. This allows cereal to track the inheritance and to avoid making
|
||||
duplicate copies during serialization.
|
||||
|
||||
It is safe to use virtual_base_class in all circumstances for serializing base
|
||||
classes, even in cases where virtual inheritance does not take place, though it may be
|
||||
slightly faster to utilize cereal::base_class<> if you do not need to worry about
|
||||
virtual inheritance.
|
||||
|
||||
This also automatically registers polymorphic relation between the base and derived
|
||||
class, assuming they are indeed polymorphic. Note this is not the same as polymorphic
|
||||
type registration. For more information see the documentation on polymorphism. If using
|
||||
a polymorphic class, be sure to include support for polymorphism
|
||||
(cereal/types/polymorphic.hpp).
|
||||
|
||||
\sa base_class
|
||||
|
||||
@code{.cpp}
|
||||
struct MyBase
|
||||
{
|
||||
int x;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x );
|
||||
}
|
||||
};
|
||||
|
||||
struct MyLeft : virtual MyBase //<-- Note the virtual inheritance
|
||||
{
|
||||
int y;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::virtual_base_class<MyBase>( this ) );
|
||||
ar( y );
|
||||
}
|
||||
};
|
||||
|
||||
struct MyRight : virtual MyBase
|
||||
{
|
||||
int z;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::virtual_base_clas<MyBase>( this ) );
|
||||
ar( z );
|
||||
}
|
||||
};
|
||||
|
||||
// diamond virtual inheritance; contains one copy of each base class
|
||||
struct MyDerived : virtual MyLeft, virtual MyRight
|
||||
{
|
||||
int a;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::virtual_base_class<MyLeft>( this ) ); // safely serialize data
|
||||
members in MyLeft ar( cereal::virtual_base_class<MyRight>( this ) ); // safely
|
||||
serialize data members in MyRight ar( a );
|
||||
|
||||
// Because we used virtual_base_class, cereal will ensure that only one instance
|
||||
of MyBase is
|
||||
// serialized as we traverse the inheritance heirarchy. This means that there will
|
||||
be one copy
|
||||
// each of the variables x, y, z, and a
|
||||
|
||||
// If we had chosen to use static_cast<> instead, cereal would perform no tracking
|
||||
and
|
||||
// assume that every base class should be serialized (in this case leading to a
|
||||
duplicate
|
||||
// serialization of MyBase due to diamond inheritance
|
||||
};
|
||||
}
|
||||
@endcode */
|
||||
template <class Base>
|
||||
struct virtual_base_class : private traits::detail::BaseCastBase
|
||||
{
|
||||
template <class Derived>
|
||||
virtual_base_class(Derived const* derived)
|
||||
: base_ptr(const_cast<Base*>(static_cast<Base const*>(derived)))
|
||||
{
|
||||
static_assert(std::is_base_of<Base, Derived>::value,
|
||||
"Can only use virtual_base_class on a valid base class");
|
||||
base_class_detail::RegisterPolymorphicBaseClass<Base, Derived>::bind();
|
||||
}
|
||||
|
||||
Base* base_ptr;
|
||||
};
|
||||
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
#endif // TIMEMORY_CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
-143
@@ -1,143 +0,0 @@
|
||||
/*! \file common.hpp
|
||||
\brief Support common types - always included automatically
|
||||
\ingroup OtherTypes */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TIMEMORY_CEREAL_TYPES_COMMON_HPP_
|
||||
#define TIMEMORY_CEREAL_TYPES_COMMON_HPP_
|
||||
|
||||
#include "timemory/tpls/cereal/cereal/cereal.hpp"
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
namespace common_detail
|
||||
{
|
||||
//! Serialization for arrays if BinaryData is supported and we are arithmetic
|
||||
/*! @internal */
|
||||
template <class Archive, class T>
|
||||
inline void
|
||||
serializeArray(Archive& ar, T& array, std::true_type /* binary_supported */)
|
||||
{
|
||||
ar(binary_data(array, sizeof(array)));
|
||||
}
|
||||
|
||||
//! Serialization for arrays if BinaryData is not supported or we are not arithmetic
|
||||
/*! @internal */
|
||||
template <class Archive, class T>
|
||||
inline void
|
||||
serializeArray(Archive& ar, T& array, std::false_type /* binary_supported */)
|
||||
{
|
||||
for(auto& i : array)
|
||||
ar(i);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Gets the underlying type of an enum
|
||||
/*! @internal */
|
||||
template <class T, bool IsEnum>
|
||||
struct enum_underlying_type : std::false_type
|
||||
{};
|
||||
|
||||
//! Gets the underlying type of an enum
|
||||
/*! Specialization for when we actually have an enum
|
||||
@internal */
|
||||
template <class T>
|
||||
struct enum_underlying_type<T, true>
|
||||
{
|
||||
using type = typename std::underlying_type<T>::type;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
//! Checks if a type is an enum
|
||||
/*! This is needed over simply calling std::is_enum because the type
|
||||
traits checking at compile time will attempt to call something like
|
||||
load_minimal with a special NoConvertRef struct that wraps up the true type.
|
||||
|
||||
This will strip away any of that and also expose the true underlying type.
|
||||
@internal */
|
||||
template <class T>
|
||||
class is_enum
|
||||
{
|
||||
private:
|
||||
using DecayedT = typename std::decay<T>::type;
|
||||
using StrippedT = typename ::tim::cereal::traits::strip_minimal<DecayedT>::type;
|
||||
|
||||
public:
|
||||
static const bool value = std::is_enum<StrippedT>::value;
|
||||
using type = StrippedT;
|
||||
using base_type = typename enum_underlying_type<StrippedT, value>::type;
|
||||
};
|
||||
} // namespace common_detail
|
||||
|
||||
//! Saving for enum types
|
||||
template <class Archive, class T>
|
||||
inline typename std::enable_if<common_detail::is_enum<T>::value,
|
||||
typename common_detail::is_enum<T>::base_type>::type
|
||||
TIMEMORY_CEREAL_SAVE_MINIMAL_FUNCTION_NAME(Archive const&, T const& t)
|
||||
{
|
||||
return static_cast<typename common_detail::is_enum<T>::base_type>(t);
|
||||
}
|
||||
|
||||
//! Loading for enum types
|
||||
template <class Archive, class T>
|
||||
inline typename std::enable_if<common_detail::is_enum<T>::value, void>::type
|
||||
TIMEMORY_CEREAL_LOAD_MINIMAL_FUNCTION_NAME(
|
||||
Archive const&, T&& t, typename common_detail::is_enum<T>::base_type const& value)
|
||||
{
|
||||
t = reinterpret_cast<typename common_detail::is_enum<T>::type const&>(value);
|
||||
}
|
||||
|
||||
//! Serialization for raw pointers
|
||||
/*! This exists only to throw a static_assert to let users know we don't support raw
|
||||
* pointers. */
|
||||
template <class Archive, class T>
|
||||
inline void
|
||||
TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(Archive&, T*&)
|
||||
{
|
||||
static_assert(
|
||||
cereal::traits::detail::delay_static_assert<T>::value,
|
||||
"Cereal does not support serializing raw pointers - please use a smart pointer");
|
||||
}
|
||||
|
||||
//! Serialization for C style arrays
|
||||
template <class Archive, class T>
|
||||
inline typename std::enable_if<std::is_array<T>::value, void>::type
|
||||
TIMEMORY_CEREAL_SERIALIZE_FUNCTION_NAME(Archive& ar, T& array)
|
||||
{
|
||||
common_detail::serializeArray(
|
||||
ar, array, std::integral_constant < bool,
|
||||
traits::is_output_serializable<BinaryData<T>, Archive>::value&&
|
||||
std::is_arithmetic<typename std::remove_all_extents<T>::type>::value >
|
||||
());
|
||||
}
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
#endif // TIMEMORY_CEREAL_TYPES_COMMON_HPP_
|
||||
@@ -1,706 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef TIMEMORY_UTILITY_ARGPARSE_CPP_
|
||||
#define TIMEMORY_UTILITY_ARGPARSE_CPP_
|
||||
|
||||
#include "timemory/utility/macros.hpp"
|
||||
|
||||
#if !defined(TIMEMORY_UTILITY_HEADER_MODE)
|
||||
# include "timemory/utility/argparse.hpp"
|
||||
#endif
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace argparse
|
||||
{
|
||||
TIMEMORY_UTILITY_INLINE
|
||||
argument_vector::argument_vector(int& argc, char**& argv)
|
||||
: base_type()
|
||||
{
|
||||
reserve(argc);
|
||||
for(int i = 0; i < argc; ++i)
|
||||
push_back(argv[i]);
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE
|
||||
argument_vector::argument_vector(int& argc, const char**& argv)
|
||||
: base_type()
|
||||
{
|
||||
reserve(argc);
|
||||
for(int i = 0; i < argc; ++i)
|
||||
push_back(argv[i]);
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE
|
||||
argument_vector::argument_vector(int& argc, const char* const*& argv)
|
||||
{
|
||||
reserve(argc);
|
||||
for(int i = 0; i < argc; ++i)
|
||||
push_back(argv[i]);
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_vector::cargs_t
|
||||
argument_vector::get_execv(const base_type& _prepend, size_t _beg, size_t _end) const
|
||||
{
|
||||
std::stringstream cmdss;
|
||||
// find the end if not specified
|
||||
_end = std::min<size_t>(size(), _end);
|
||||
// determine the number of arguments
|
||||
auto _argc = (_end - _beg) + _prepend.size();
|
||||
// create the new C argument array, add an extra entry at the end which will
|
||||
// always be a null pointer because that is how execv determines the end
|
||||
char** _argv = new char*[_argc + 1];
|
||||
|
||||
// ensure all arguments are null pointers initially
|
||||
for(size_t i = 0; i < _argc + 1; ++i)
|
||||
_argv[i] = nullptr;
|
||||
|
||||
// add the prepend list
|
||||
size_t _idx = 0;
|
||||
for(const auto& itr : _prepend)
|
||||
_argv[_idx++] = helpers::strdup(itr.c_str());
|
||||
|
||||
// copy over the arguments stored internally from the range specified
|
||||
for(auto i = _beg; i < _end; ++i)
|
||||
_argv[_idx++] = helpers::strdup(this->at(i).c_str());
|
||||
|
||||
// add check that last argument really is a nullptr
|
||||
assert(_argv[_argc] == nullptr);
|
||||
|
||||
// create the command string
|
||||
for(size_t i = 0; i < _argc; ++i)
|
||||
cmdss << " " << _argv[i];
|
||||
auto cmd = cmdss.str().substr(1);
|
||||
|
||||
// return a new (int argc, char** argv) and subtract 1 bc nullptr in last entry
|
||||
// does not count as argc
|
||||
return cargs_t(_argc - 1, _argv, cmd);
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_vector::cargs_t
|
||||
argument_vector::get_execv(size_t _beg, size_t _end) const
|
||||
{
|
||||
return get_execv(base_type{}, _beg, _end);
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE void
|
||||
argument_parser::print_help(const std::string& _extra)
|
||||
{
|
||||
std::stringstream _usage;
|
||||
if(!m_desc.empty())
|
||||
_usage << "[" << m_desc << "] ";
|
||||
_usage << "Usage: " << m_bin;
|
||||
|
||||
std::cerr << _usage.str();
|
||||
|
||||
std::stringstream _sshort_desc;
|
||||
auto _indent = _usage.str().length() + 2;
|
||||
size_t _ncnt = 0;
|
||||
for(auto& a : m_arguments)
|
||||
{
|
||||
std::string name = a.m_names.at(0);
|
||||
if(name.empty() || name.find_first_of('-') > name.find_first_not_of(" -"))
|
||||
continue;
|
||||
// select the first long option
|
||||
for(size_t n = 1; n < a.m_names.size(); ++n)
|
||||
{
|
||||
if(name.find("--") == 0)
|
||||
break;
|
||||
else if(a.m_names.at(n).find("--") == 0)
|
||||
{
|
||||
name = a.m_names.at(n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(name.length() > 0)
|
||||
{
|
||||
if(_ncnt++ > 0)
|
||||
_sshort_desc << "\n " << std::setw(_indent) << " " << name;
|
||||
else
|
||||
_sshort_desc << " " << name;
|
||||
|
||||
_sshort_desc << " (";
|
||||
if(a.m_count != argument::Count::ANY)
|
||||
_sshort_desc << "count: " << a.m_count;
|
||||
else if(a.m_min_count != argument::Count::ANY)
|
||||
_sshort_desc << "min: " << a.m_min_count;
|
||||
else if(a.m_max_count != argument::Count::ANY)
|
||||
_sshort_desc << "max: " << a.m_max_count;
|
||||
else
|
||||
_sshort_desc << "count: unlimited";
|
||||
if(!a.m_dtype.empty())
|
||||
_sshort_desc << ", dtype: " << a.m_dtype;
|
||||
else if(a.m_count == 0 ||
|
||||
(a.m_count == argument::Count::ANY && a.m_max_count == 1))
|
||||
_sshort_desc << ", dtype: bool" << a.m_dtype;
|
||||
_sshort_desc << ")";
|
||||
}
|
||||
}
|
||||
|
||||
std::string _short_desc;
|
||||
if(!_sshort_desc.str().empty())
|
||||
{
|
||||
_short_desc.append("[" + _sshort_desc.str());
|
||||
std::stringstream _tmp;
|
||||
_tmp << "\n" << std::setw(_indent) << "]";
|
||||
_short_desc.append(_tmp.str());
|
||||
}
|
||||
|
||||
if(m_positional_arguments.empty())
|
||||
{
|
||||
std::cerr << " " << _short_desc << " " << _extra << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " " << _short_desc;
|
||||
if(!_short_desc.empty())
|
||||
std::cerr << "\n" << std::setw(_indent - 2) << " ";
|
||||
for(auto& itr : m_positional_arguments)
|
||||
{
|
||||
std::cerr << " " << helpers::ltrim(itr.m_names.at(0), [](int c) -> bool {
|
||||
return c != static_cast<int>('-');
|
||||
});
|
||||
}
|
||||
|
||||
int current = 0;
|
||||
for(auto& v : m_positional_map)
|
||||
{
|
||||
if(v.first != argument::Position::LastArgument)
|
||||
{
|
||||
for(; current < v.first; ++current)
|
||||
std::cerr << " [" << current << "]";
|
||||
std::cerr << " ["
|
||||
<< helpers::ltrim(
|
||||
m_arguments[static_cast<size_t>(v.second)].m_names.at(0),
|
||||
[](int c) -> bool { return c != static_cast<int>('-'); })
|
||||
<< "]";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << " ... ["
|
||||
<< helpers::ltrim(
|
||||
m_arguments[static_cast<size_t>(v.second)].m_names.at(0),
|
||||
[](int c) -> bool { return c != static_cast<int>('-'); })
|
||||
<< "]";
|
||||
}
|
||||
}
|
||||
std::cerr << " " << _extra << std::endl;
|
||||
}
|
||||
|
||||
std::cerr << "\nOptions:" << std::endl;
|
||||
for(auto& a : m_arguments)
|
||||
{
|
||||
std::string name = a.m_names.at(0);
|
||||
for(size_t n = 1; n < a.m_names.size(); ++n)
|
||||
name.append(", " + a.m_names[n]);
|
||||
std::stringstream ss;
|
||||
ss << name;
|
||||
if(a.m_choices.size() > 0)
|
||||
{
|
||||
ss << " [";
|
||||
auto itr = a.m_choices.begin();
|
||||
ss << " " << *itr++;
|
||||
for(; itr != a.m_choices.end(); ++itr)
|
||||
ss << " | " << *itr;
|
||||
ss << " ] ";
|
||||
}
|
||||
std::stringstream prefix;
|
||||
prefix << " " << std::setw(m_width) << std::left << ss.str();
|
||||
std::cerr << std::left << prefix.str();
|
||||
|
||||
auto desc = a.m_desc;
|
||||
if(ss.str().length() >= static_cast<size_t>(m_width))
|
||||
desc = std::string("\n%{NEWLINE}%") + desc;
|
||||
|
||||
{
|
||||
// replace %{INDENT}% with indentation
|
||||
const std::string indent_key = "%{INDENT}%";
|
||||
const auto npos = std::string::npos;
|
||||
auto pos = npos;
|
||||
std::stringstream indent;
|
||||
indent << std::setw(prefix.str().length()) << "";
|
||||
while((pos = desc.find(indent_key)) != npos)
|
||||
desc = desc.replace(pos, indent_key.length(), indent.str());
|
||||
}
|
||||
|
||||
{
|
||||
// replace %{NEWLINE}% with indentation
|
||||
const std::string indent_key = "%{NEWLINE}%";
|
||||
const auto npos = std::string::npos;
|
||||
auto pos = npos;
|
||||
std::stringstream indent;
|
||||
indent << std::setw(m_width + 5) << "";
|
||||
while((pos = desc.find(indent_key)) != npos)
|
||||
desc = desc.replace(pos, indent_key.length(), indent.str());
|
||||
}
|
||||
|
||||
std::cerr << " " << std::setw(m_width) << desc;
|
||||
|
||||
if(a.m_required)
|
||||
std::cerr << " (Required)";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
std::cerr << '\n';
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_parser::arg_result
|
||||
argument_parser::parse_known_args(int* argc, char*** argv, strvec_t& _args,
|
||||
const std::string& _delim, int verbose_level)
|
||||
{
|
||||
// check for help flag
|
||||
auto help_check = [&](int _argc, char** _argv) {
|
||||
strset_t help_args = { "-h", "--help", "-?" };
|
||||
auto _help_req = (exists("help") ||
|
||||
(_argc > 1 && help_args.find(_argv[1]) != help_args.end()));
|
||||
if(_help_req && !exists("help"))
|
||||
{
|
||||
for(auto hitr : help_args)
|
||||
{
|
||||
auto hstr = hitr.substr(hitr.find_first_not_of('-'));
|
||||
auto itr = m_name_map.find(hstr);
|
||||
if(itr != m_name_map.end())
|
||||
m_arguments[static_cast<size_t>(itr->second)].m_found = true;
|
||||
}
|
||||
}
|
||||
return _help_req;
|
||||
};
|
||||
|
||||
// check for a dash in th command line
|
||||
bool _pdash = false;
|
||||
for(int i = 1; i < *argc; ++i)
|
||||
{
|
||||
if((*argv)[i] == std::string("--"))
|
||||
_pdash = true;
|
||||
}
|
||||
|
||||
// parse the known args and get the remaining argc/argv
|
||||
auto _pargs = parse_known_args(*argc, *argv, _args, _delim, verbose_level);
|
||||
auto _perrc = std::get<0>(_pargs);
|
||||
auto _pargc = std::get<1>(_pargs);
|
||||
auto _pargv = std::get<2>(_pargs);
|
||||
|
||||
// check if help was requested before the dash (if dash exists)
|
||||
if(help_check((_pdash) ? 0 : _pargc, _pargv))
|
||||
return arg_result{ "help requested" };
|
||||
|
||||
// assign the argc and argv
|
||||
*argc = _pargc;
|
||||
*argv = _pargv;
|
||||
|
||||
return _perrc;
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_parser::known_args_t
|
||||
argument_parser::parse_known_args(int argc, char** argv, strvec_t& _args,
|
||||
const std::string& _delim, int verbose_level)
|
||||
{
|
||||
int _cmdc = argc; // the argc after known args removed
|
||||
char** _cmdv = argv; // the argv after known args removed
|
||||
// _cmdv and argv are same pointer unless delimiter is found
|
||||
|
||||
if(argc > 0)
|
||||
{
|
||||
m_bin = std::string((const char*) argv[0]);
|
||||
_args.push_back(std::string((const char*) argv[0]));
|
||||
}
|
||||
|
||||
for(int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string _arg = argv[i];
|
||||
if(_arg == _delim)
|
||||
{
|
||||
_cmdc = argc - i;
|
||||
_cmdv = new char*[_cmdc + 1];
|
||||
_cmdv[_cmdc] = nullptr;
|
||||
_cmdv[0] = helpers::strdup(argv[0]);
|
||||
int k = 1;
|
||||
for(int j = i + 1; j < argc; ++j, ++k)
|
||||
_cmdv[k] = helpers::strdup(argv[j]);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
_args.push_back(std::string((const char*) argv[i]));
|
||||
}
|
||||
}
|
||||
|
||||
auto cmd_string = [](int _ac, char** _av) {
|
||||
std::stringstream ss;
|
||||
for(int i = 0; i < _ac; ++i)
|
||||
ss << _av[i] << " ";
|
||||
return ss.str();
|
||||
};
|
||||
|
||||
if((_cmdc > 0 && verbose_level > 0) || verbose_level > 1)
|
||||
std::cerr << "\n";
|
||||
|
||||
if(verbose_level > 1)
|
||||
{
|
||||
std::cerr << "[original]> " << cmd_string(argc, argv) << std::endl;
|
||||
std::cerr << "[cfg-args]> ";
|
||||
for(auto& itr : _args)
|
||||
std::cerr << itr << " ";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
if(_cmdc > 0 && verbose_level > 0)
|
||||
std::cerr << "[command]> " << cmd_string(_cmdc, _cmdv) << "\n\n";
|
||||
|
||||
return known_args_t{ parse(_args, verbose_level), _cmdc, _cmdv };
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_parser::arg_result
|
||||
argument_parser::parse(const std::vector<std::string>& _args, int verbose_level)
|
||||
{
|
||||
if(verbose_level > 0)
|
||||
{
|
||||
std::cerr << "[argparse::parse]> parsing '";
|
||||
for(const auto& itr : _args)
|
||||
std::cerr << itr << " ";
|
||||
std::cerr << "'" << '\n';
|
||||
}
|
||||
|
||||
for(auto& a : m_arguments)
|
||||
a.m_callback(a.m_default);
|
||||
for(auto& a : m_positional_arguments)
|
||||
a.m_callback(a.m_default);
|
||||
|
||||
using argmap_t = std::map<std::string, argument*>;
|
||||
|
||||
argmap_t m_arg_map = {};
|
||||
arg_result err;
|
||||
int argc = _args.size();
|
||||
// the set of options which use a single leading dash but are longer than
|
||||
// one character, e.g. -LS ...
|
||||
std::set<std::string> long_short_opts;
|
||||
if(_args.size() > 1)
|
||||
{
|
||||
auto is_leading_dash = [](int c) -> bool { return c != static_cast<int>('-'); };
|
||||
// build name map
|
||||
for(auto& a : m_arguments)
|
||||
{
|
||||
for(auto& n : a.m_names)
|
||||
{
|
||||
auto nleading_dash = helpers::lcount(n, is_leading_dash);
|
||||
std::string name = helpers::ltrim(n, is_leading_dash);
|
||||
if(name.empty())
|
||||
continue;
|
||||
if(m_name_map.find(name) != m_name_map.end())
|
||||
return arg_result("Duplicate of argument name: " + n);
|
||||
m_name_map[name] = a.m_index;
|
||||
m_arg_map[name] = &a;
|
||||
if(nleading_dash == 1 && name.length() > 1)
|
||||
long_short_opts.insert(name);
|
||||
}
|
||||
if(a.m_position >= 0 || a.m_position == argument::Position::LastArgument)
|
||||
m_positional_map.at(a.m_position) = a.m_index;
|
||||
}
|
||||
|
||||
m_bin = _args.at(0);
|
||||
|
||||
// parse
|
||||
std::string current_arg;
|
||||
size_t arg_len;
|
||||
for(int argv_index = 1; argv_index < argc; ++argv_index)
|
||||
{
|
||||
current_arg = _args.at(argv_index);
|
||||
arg_len = current_arg.length();
|
||||
if(arg_len == 0)
|
||||
continue;
|
||||
if(argv_index == argc - 1 &&
|
||||
m_positional_map.find(argument::Position::LastArgument) !=
|
||||
m_positional_map.end())
|
||||
{
|
||||
err = end_argument();
|
||||
arg_result b = err;
|
||||
err = add_value(current_arg, argument::Position::LastArgument);
|
||||
if(b)
|
||||
return b;
|
||||
// return (m_error_func(*this, b), b);
|
||||
if(err)
|
||||
return (m_error_func(*this, err), err);
|
||||
continue;
|
||||
}
|
||||
|
||||
// count number of leading dashes
|
||||
auto nleading_dash = helpers::lcount(current_arg, is_leading_dash);
|
||||
// ignores the case if the arg is just a '-'
|
||||
// look for -a (short) or --arg (long) args
|
||||
bool is_arg = (nleading_dash > 0 && arg_len > 1 && arg_len != nleading_dash)
|
||||
? true
|
||||
: false;
|
||||
|
||||
if(is_arg && !helpers::is_numeric(current_arg))
|
||||
{
|
||||
err = end_argument();
|
||||
if(err)
|
||||
return (m_error_func(*this, err), err);
|
||||
|
||||
auto name = current_arg.substr(nleading_dash);
|
||||
auto islong = (nleading_dash > 1 || long_short_opts.count(name) > 0);
|
||||
err = begin_argument(name, islong, argv_index);
|
||||
if(err)
|
||||
return (m_error_func(*this, err), err);
|
||||
}
|
||||
else if(current_arg.length() > 0)
|
||||
{
|
||||
// argument value
|
||||
err = add_value(current_arg, argv_index);
|
||||
if(err)
|
||||
return (m_error_func(*this, err), err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the help
|
||||
if(m_help_enabled && exists("help"))
|
||||
return arg_result("help requested");
|
||||
|
||||
err = end_argument();
|
||||
if(err)
|
||||
return (m_error_func(*this, err), err);
|
||||
|
||||
// check requirements
|
||||
for(auto& a : m_arguments)
|
||||
{
|
||||
if(a.m_required && !a.m_found)
|
||||
{
|
||||
return arg_result("Required argument not found: " + a.m_names.at(0));
|
||||
}
|
||||
if(a.m_position >= 0 && argc >= a.m_position && !a.m_found)
|
||||
{
|
||||
return arg_result("argument " + a.m_names.at(0) + " expected in position " +
|
||||
std::to_string(a.m_position));
|
||||
}
|
||||
}
|
||||
|
||||
// check requirements
|
||||
for(auto& a : m_positional_arguments)
|
||||
{
|
||||
if(a.m_required && !a.m_found)
|
||||
return arg_result("Required argument not found: " + a.m_names.at(0));
|
||||
}
|
||||
|
||||
// check all the counts have been satisfied
|
||||
for(auto& a : m_arguments)
|
||||
{
|
||||
if(a.m_found && a.m_default == nullptr)
|
||||
{
|
||||
auto cnt_err = check_count(a);
|
||||
if(cnt_err)
|
||||
return cnt_err;
|
||||
}
|
||||
}
|
||||
|
||||
// execute the global actions
|
||||
for(auto& itr : m_actions)
|
||||
{
|
||||
if(itr.first(*this))
|
||||
itr.second(*this);
|
||||
}
|
||||
|
||||
// execute the argument-specific actions
|
||||
for(auto& itr : m_arg_map)
|
||||
{
|
||||
if(exists(itr.first))
|
||||
itr.second->execute_actions(*this);
|
||||
}
|
||||
|
||||
return arg_result{};
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_parser::arg_result
|
||||
argument_parser::begin_argument(const std::string& arg, bool longarg, int position)
|
||||
{
|
||||
auto it = m_positional_map.find(position);
|
||||
if(it != m_positional_map.end())
|
||||
{
|
||||
arg_result err = end_argument();
|
||||
argument& a = m_arguments[static_cast<size_t>(it->second)];
|
||||
a.m_values.push_back(arg);
|
||||
a.m_found = true;
|
||||
return err;
|
||||
}
|
||||
if(m_current != -1)
|
||||
{
|
||||
return arg_result("Current argument left open");
|
||||
}
|
||||
size_t name_end = helpers::find_punct(arg);
|
||||
std::string arg_name = arg.substr(0, name_end);
|
||||
if(longarg)
|
||||
{
|
||||
int equal_pos = helpers::find_equiv(arg);
|
||||
auto nmf = m_name_map.find(arg_name);
|
||||
if(nmf == m_name_map.end())
|
||||
{
|
||||
arg_name = arg.substr(0, equal_pos);
|
||||
nmf = m_name_map.find(arg_name);
|
||||
}
|
||||
if(nmf == m_name_map.end())
|
||||
{
|
||||
return arg_result("Unrecognized command line option '" + arg_name + "'");
|
||||
}
|
||||
m_current = nmf->second;
|
||||
m_arguments[static_cast<size_t>(nmf->second)].m_found = true;
|
||||
if(equal_pos == 0 || (equal_pos < 0 && arg_name.length() < arg.length()))
|
||||
{
|
||||
// malformed argument
|
||||
return arg_result("Malformed argument: " + arg);
|
||||
}
|
||||
else if(equal_pos > 0)
|
||||
{
|
||||
std::string arg_value = arg.substr(name_end + 1);
|
||||
add_value(arg_value, position);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_result r;
|
||||
if(arg_name.length() == 1)
|
||||
{
|
||||
return begin_argument(arg, true, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(char& c : arg_name)
|
||||
{
|
||||
r = begin_argument(std::string(1, c), true, position);
|
||||
if(r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
r = end_argument();
|
||||
if(r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return arg_result{};
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_parser::arg_result
|
||||
argument_parser::add_value(const std::string& value, int location)
|
||||
{
|
||||
auto unnamed = [&]() {
|
||||
auto itr = m_positional_map.find(location);
|
||||
if(itr != m_positional_map.end())
|
||||
{
|
||||
argument& a = m_arguments[static_cast<size_t>(itr->second)];
|
||||
a.m_values.push_back(value);
|
||||
a.m_found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto idx = m_positional_values.size();
|
||||
m_positional_values.emplace(idx, value);
|
||||
if(idx < m_positional_arguments.size())
|
||||
{
|
||||
auto& a = m_positional_arguments.at(idx);
|
||||
a.m_found = true;
|
||||
auto err = a.check_choice(value);
|
||||
if(err)
|
||||
return err;
|
||||
a.m_values.push_back(value);
|
||||
a.execute_actions(*this);
|
||||
}
|
||||
}
|
||||
return arg_result{};
|
||||
};
|
||||
|
||||
if(m_current >= 0)
|
||||
{
|
||||
arg_result err;
|
||||
size_t c = static_cast<size_t>(m_current);
|
||||
consume_parameters(c);
|
||||
argument& a = m_arguments[static_cast<size_t>(m_current)];
|
||||
|
||||
err = a.check_choice(value);
|
||||
if(err)
|
||||
return err;
|
||||
|
||||
auto num_values = [&]() { return static_cast<int>(a.m_values.size()); };
|
||||
|
||||
// check {m_count, m_max_count} > COUNT::ANY && m_values.size() >= {value}
|
||||
if((a.m_count >= 0 && num_values() >= a.m_count) ||
|
||||
(a.m_max_count >= 0 && num_values() >= a.m_max_count))
|
||||
{
|
||||
err = end_argument();
|
||||
if(err)
|
||||
return err;
|
||||
return unnamed();
|
||||
}
|
||||
|
||||
a.m_values.push_back(value);
|
||||
|
||||
// check {m_count, m_max_count} > COUNT::ANY && m_values.size() >= {value}
|
||||
if((a.m_count >= 0 && num_values() >= a.m_count) ||
|
||||
(a.m_max_count >= 0 && num_values() >= a.m_max_count))
|
||||
{
|
||||
err = end_argument();
|
||||
if(err)
|
||||
return err;
|
||||
}
|
||||
return arg_result{};
|
||||
}
|
||||
|
||||
return unnamed();
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE argument_parser::arg_result
|
||||
argument_parser::end_argument()
|
||||
{
|
||||
if(m_current >= 0)
|
||||
{
|
||||
argument& a = m_arguments[static_cast<size_t>(m_current)];
|
||||
m_current = -1;
|
||||
if(static_cast<int>(a.m_values.size()) < a.m_count)
|
||||
return arg_result("Too few arguments given for " + a.m_names.at(0));
|
||||
if(a.m_max_count >= 0)
|
||||
{
|
||||
if(static_cast<int>(a.m_values.size()) > a.m_max_count)
|
||||
return arg_result("Too many arguments given for " + a.m_names.at(0));
|
||||
}
|
||||
else if(a.m_count >= 0)
|
||||
{
|
||||
if(static_cast<int>(a.m_values.size()) > a.m_count)
|
||||
return arg_result("Too many arguments given for " + a.m_names.at(0));
|
||||
}
|
||||
}
|
||||
return arg_result{};
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE std::ostream&
|
||||
operator<<(std::ostream& os, const argument_parser::arg_result& r)
|
||||
{
|
||||
os << r.what();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace argparse
|
||||
} // namespace tim
|
||||
|
||||
#endif
|
||||
تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
Diff را بارگزاری کن
@@ -1,205 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \file timemory/utility/bits/macros.hpp
|
||||
* \headerfile timemory/utility/bits/macros.hpp "timemory/utility/bits/macros.hpp"
|
||||
* Deprecated macros
|
||||
*/
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// ALL OF THESE MACROS ARE DEPRECATED!
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#pragma once
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// OBJECT MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_OBJECT(type, ...) TIMEMORY_BLANK_MARKER(type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_OBJECT(type, ...) TIMEMORY_BASIC_MARKER(type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_OBJECT(type, ...) TIMEMORY_MARKER(type, __VA_ARGS__)
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// INSTANCE MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_INSTANCE(type, ...) TIMEMORY_BLANK_HANDLE(type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_INSTANCE(type, ...) TIMEMORY_BASIC_HANDLE(type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_INSTANCE(type, ...) TIMEMORY_HANDLE(type, __VA_ARGS__)
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// AUTO_TUPLE MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// DEPRECATED use macros in timemory/variadic/macros.hpp!
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_AUTO_TUPLE(auto_tuple_type, ...) \
|
||||
TIMEMORY_BLANK_MARKER(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_AUTO_TUPLE(auto_tuple_type, ...) \
|
||||
TIMEMORY_BASIC_MARKER(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_AUTO_TUPLE(auto_tuple_type, ...) \
|
||||
TIMEMORY_MARKER(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// caliper versions -- DEPRECATED use macros in timemory/variadic/macros.hpp!
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_AUTO_TUPLE_CALIPER(id, auto_tuple_type, ...) \
|
||||
TIMEMORY_BLANK_CALIPER(id, auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_AUTO_TUPLE_CALIPER(id, auto_tuple_type, ...) \
|
||||
TIMEMORY_BASIC_CALIPER(id, auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_AUTO_TUPLE_CALIPER(id, auto_tuple_type, ...) \
|
||||
TIMEMORY_CALIPER(id, auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// instance versions -- DEPRECATED use macros in timemory/variadic/macros.hpp!
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_AUTO_TUPLE_INSTANCE(auto_tuple_type, ...) \
|
||||
TIMEMORY_BLANK_HANDLE(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_AUTO_TUPLE_INSTANCE(auto_tuple_type, ...) \
|
||||
TIMEMORY_BASIC_HANDLE(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_AUTO_TUPLE_INSTANCE(auto_tuple_type, ...) \
|
||||
TIMEMORY_HANDLE(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// debug versions -- DEPRECATED use macros in timemory/variadic/macros.hpp!
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_DEBUG_BASIC_AUTO_TUPLE(auto_tuple_type, ...) \
|
||||
TIMEMORY_DEBUG_BASIC_MARKER(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_DEBUG_AUTO_TUPLE(auto_tuple_type, ...) \
|
||||
TIMEMORY_DEBUG_MARKER(auto_tuple_type, __VA_ARGS__)
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// AUTO_LIST MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_AUTO_LIST(auto_list_type, ...) \
|
||||
TIMEMORY_BLANK_MARKER(auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_AUTO_LIST(auto_list_type, ...) \
|
||||
TIMEMORY_BASIC_MARKER(auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_AUTO_LIST(auto_list_type, ...) \
|
||||
TIMEMORY_MARKER(auto_list_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// caliper versions
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_AUTO_LIST_CALIPER(id, auto_list_type, ...) \
|
||||
TIMEMORY_BLANK_CALIPER(id, auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_AUTO_LIST_CALIPER(id, auto_list_type, ...) \
|
||||
TIMEMORY_BASIC_CALIPER(id, auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_AUTO_LIST_CALIPER(id, auto_list_type, ...) \
|
||||
TIMEMORY_CALIPER(id, auto_list_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// instance versions
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BLANK_AUTO_LIST_INSTANCE(auto_list_type, ...) \
|
||||
TIMEMORY_BLANK_HANDLE(auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_BASIC_AUTO_LIST_INSTANCE(auto_list_type, ...) \
|
||||
TIMEMORY_BASIC_HANDLE(auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_AUTO_LIST_INSTANCE(auto_list_type, ...) \
|
||||
TIMEMORY_HANDLE(auto_list_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// debug versions
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_DEBUG_BASIC_AUTO_LIST(auto_list_type, ...) \
|
||||
TIMEMORY_DEBUG_BASIC_MARKER(auto_list_type, __VA_ARGS__)
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_DEBUG_AUTO_LIST(auto_list_type, ...) \
|
||||
TIMEMORY_DEBUG_MARKER(auto_list_type, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_CALIPER_MARK_STREAM_BEGIN(id, stream) \
|
||||
TIMEMORY_CALIPER_APPLY(id, mark_begin, stream)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
/// \deprecated
|
||||
#define TIMEMORY_CALIPER_MARK_STREAM_END(id, stream) \
|
||||
TIMEMORY_CALIPER_APPLY(id, mark_end, stream)
|
||||
@@ -1,305 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/macros/attributes.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#if defined(TIMEMORY_CORE_SOURCE)
|
||||
# define TIMEMORY_UTILITY_SOURCE
|
||||
#elif defined(TIMEMORY_USE_CORE_EXTERN)
|
||||
# define TIMEMORY_USE_UTILITY_EXTERN
|
||||
#endif
|
||||
//
|
||||
#if defined(TIMEMORY_USE_EXTERN) && !defined(TIMEMORY_USE_UTILITY_EXTERN)
|
||||
# define TIMEMORY_USE_UTILITY_EXTERN
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Quick way to create a globally accessible setting
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
#if !defined(CREATE_STATIC_VARIABLE_ACCESSOR)
|
||||
# define CREATE_STATIC_VARIABLE_ACCESSOR(TYPE, FUNC_NAME, VARIABLE) \
|
||||
static TYPE& FUNC_NAME() \
|
||||
{ \
|
||||
static TYPE _instance = Type::VARIABLE; \
|
||||
return _instance; \
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if !defined(CREATE_STATIC_FUNCTION_ACCESSOR)
|
||||
# define CREATE_STATIC_FUNCTION_ACCESSOR(TYPE, FUNC_NAME, VARIABLE) \
|
||||
static TYPE& FUNC_NAME() \
|
||||
{ \
|
||||
static TYPE _instance = Type::VARIABLE(); \
|
||||
return _instance; \
|
||||
}
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// stringify some macro -- uses TIMEMORY_STRINGIZE2 which does the actual
|
||||
// "stringify-ing" after the macro has been substituted by it's result
|
||||
#if !defined(TIMEMORY_STRINGIZE)
|
||||
# define TIMEMORY_STRINGIZE(X) TIMEMORY_STRINGIZE2(X)
|
||||
#endif
|
||||
|
||||
// actual stringifying
|
||||
#if !defined(TIMEMORY_STRINGIZE2)
|
||||
# define TIMEMORY_STRINGIZE2(X) # X
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_TRUNCATED_FILE_STRING)
|
||||
# define TIMEMORY_TRUNCATED_FILE_STRING(FILE) \
|
||||
[]() { \
|
||||
std::string _f{ FILE }; \
|
||||
auto _pos = _f.find("/timemory/"); \
|
||||
if(_pos != std::string::npos) \
|
||||
{ \
|
||||
return _f.substr(_pos + 1); \
|
||||
} \
|
||||
return _f; \
|
||||
}()
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_FILE_LINE_FUNC_STRING)
|
||||
# define TIMEMORY_FILE_LINE_FUNC_STRING \
|
||||
std::string \
|
||||
{ \
|
||||
std::string{ "[" } + TIMEMORY_TRUNCATED_FILE_STRING(__FILE__) + ":" + \
|
||||
std::to_string(__LINE__) + "@'" + __FUNCTION__ + "']" \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_PID_TID_STRING)
|
||||
# define TIMEMORY_PID_TID_STRING \
|
||||
std::string \
|
||||
{ \
|
||||
std::string{ "[pid=" } + std::to_string(::tim::process::get_id()) + \
|
||||
std::string{ "][tid=" } + std::to_string(::tim::threading::get_id()) + \
|
||||
"]" \
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Arg>
|
||||
TIMEMORY_NOINLINE auto
|
||||
timemory_proxy_value(Arg&& arg, int) -> decltype(arg.proxy_value())
|
||||
{
|
||||
return arg.proxy_value();
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
TIMEMORY_NOINLINE auto
|
||||
timemory_proxy_value(Arg&& arg, long)
|
||||
{
|
||||
return std::forward<Arg>(arg);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
TIMEMORY_NOINLINE void
|
||||
timemory_print_here(const char* _pid_tid, const char* _file, int _line, const char* _func,
|
||||
Args&&... args)
|
||||
{
|
||||
fprintf(stderr, "%s[%s:%i@'%s']> ", _pid_tid, _file, _line, _func);
|
||||
fprintf(stderr, timemory_proxy_value(std::forward<Args>(args), 0)...);
|
||||
fprintf(stderr, "...\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
#if !defined(PRINT_HERE)
|
||||
# define PRINT_HERE(...) \
|
||||
timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
|
||||
TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), __LINE__, \
|
||||
__FUNCTION__, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if !defined(DEBUG_PRINT_HERE)
|
||||
# if defined(DEBUG)
|
||||
# define DEBUG_PRINT_HERE(...) \
|
||||
if(::tim::settings::debug()) \
|
||||
{ \
|
||||
timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
|
||||
TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
|
||||
__LINE__, __FUNCTION__, __VA_ARGS__); \
|
||||
}
|
||||
# else
|
||||
# define DEBUG_PRINT_HERE(...)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(VERBOSE_PRINT_HERE)
|
||||
# define VERBOSE_PRINT_HERE(VERBOSE_LEVEL, ...) \
|
||||
if(::tim::settings::verbose() >= VERBOSE_LEVEL) \
|
||||
{ \
|
||||
timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
|
||||
TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
|
||||
__LINE__, __FUNCTION__, __VA_ARGS__); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONDITIONAL_PRINT_HERE)
|
||||
# define CONDITIONAL_PRINT_HERE(CONDITION, ...) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
|
||||
TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
|
||||
__LINE__, __FUNCTION__, __VA_ARGS__); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_CONDITIONAL_BACKTRACE)
|
||||
# define TIMEMORY_CONDITIONAL_BACKTRACE(CONDITION, DEPTH) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
::tim::print_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING, \
|
||||
TIMEMORY_FILE_LINE_FUNC_STRING); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE)
|
||||
# define TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE(CONDITION, DEPTH) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
::tim::print_demangled_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING, \
|
||||
TIMEMORY_FILE_LINE_FUNC_STRING); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(PRETTY_PRINT_HERE)
|
||||
# if defined(TIMEMORY_GNU_COMPILER) || defined(TIMEMORY_CLANG_COMPILER)
|
||||
# define PRETTY_PRINT_HERE(...) \
|
||||
timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
|
||||
TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
|
||||
__LINE__, __PRETTY_FUNCTION__, __VA_ARGS__)
|
||||
# else
|
||||
# define PRETTY_PRINT_HERE(...) \
|
||||
timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
|
||||
TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
|
||||
__LINE__, __FUNCTION__, __VA_ARGS__)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_CONDITIONAL_BACKTRACE)
|
||||
# define TIMEMORY_CONDITIONAL_BACKTRACE(CONDITION, DEPTH) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
::tim::print_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE)
|
||||
# define TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE(CONDITION, DEPTH) \
|
||||
if(CONDITION) \
|
||||
{ \
|
||||
::tim::print_demangled_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
||||
template <typename... Args>
|
||||
inline void
|
||||
__LOG(std::string file, int line, const char* msg, Args&&... args)
|
||||
{
|
||||
auto _pos = file.find("/timemory/");
|
||||
if(_pos == std::string::npos)
|
||||
_pos = file.find_last_of('/');
|
||||
if(_pos != std::string::npos)
|
||||
file = file.substr(_pos);
|
||||
fprintf(stderr, "[Log @ %s:%i]> ", file.c_str(), line);
|
||||
fprintf(stderr, msg, std::forward<Args>(args)...);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline void
|
||||
__LOG(std::string file, int line, const char* msg)
|
||||
{
|
||||
if(file.find('/') != std::string::npos)
|
||||
file = file.substr(file.find_last_of('/'));
|
||||
fprintf(stderr, "[Log @ %s:%i]> %s\n", file.c_str(), line, msg);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// auto insert the file and line
|
||||
# define _LOG(...) __LOG(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename... Args>
|
||||
inline void
|
||||
_DBG(const char* msg, Args&&... args)
|
||||
{
|
||||
fprintf(stderr, msg, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline void
|
||||
_DBG(const char* msg)
|
||||
{
|
||||
fprintf(stderr, "%s", msg);
|
||||
}
|
||||
|
||||
#else
|
||||
# define _LOG(...) \
|
||||
{}
|
||||
# define _DBG(...) \
|
||||
{}
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Define macros for utility
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
#if defined(TIMEMORY_UTILITY_SOURCE)
|
||||
# define TIMEMORY_UTILITY_LINKAGE(...) __VA_ARGS__
|
||||
# define TIMEMORY_UTILITY_INLINE
|
||||
#elif defined(TIMEMORY_USE_EXTERN) || defined(TIMEMORY_USE_UTILITY_EXTERN)
|
||||
# define TIMEMORY_UTILITY_LINKAGE(...) __VA_ARGS__
|
||||
# define TIMEMORY_UTILITY_INLINE
|
||||
#else
|
||||
# define TIMEMORY_UTILITY_LINKAGE(...) inline __VA_ARGS__
|
||||
# define TIMEMORY_UTILITY_INLINE inline
|
||||
# define TIMEMORY_UTILITY_HEADER_MODE
|
||||
#endif
|
||||
@@ -1,391 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#include "timemory/macros/os.hpp"
|
||||
|
||||
#if !defined(TIMEMORY_WINDOWS)
|
||||
|
||||
# include "timemory/utility/popen.hpp"
|
||||
# include <limits>
|
||||
|
||||
# if !defined(OPEN_MAX)
|
||||
# define OPEN_MAX 1024
|
||||
# endif
|
||||
|
||||
# if !defined(NGROUPS_MAX)
|
||||
# define NGROUPS_MAX 16
|
||||
# endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern char** environ;
|
||||
}
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace popen
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
struct group_info
|
||||
{
|
||||
int ngroups = -1;
|
||||
gid_t group_id;
|
||||
uid_t user_id;
|
||||
gid_t groups[NGROUPS_MAX];
|
||||
};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
inline group_info&
|
||||
get_group_info()
|
||||
{
|
||||
static group_info _instance;
|
||||
return _instance;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
void
|
||||
drop_privileges(int permanent)
|
||||
{
|
||||
gid_t newgid = getgid();
|
||||
gid_t oldgid = getegid();
|
||||
uid_t newuid = getuid();
|
||||
uid_t olduid = geteuid();
|
||||
|
||||
if(permanent == 0)
|
||||
{
|
||||
// Save information about the privileges that are being dropped so that they
|
||||
// can be restored later.
|
||||
//
|
||||
get_group_info().group_id = oldgid;
|
||||
get_group_info().user_id = olduid;
|
||||
get_group_info().ngroups = getgroups(NGROUPS_MAX, get_group_info().groups);
|
||||
}
|
||||
|
||||
// If root privileges are to be dropped, be sure to pare down the ancillary
|
||||
// groups for the process before doing anything else because the setgroups( )
|
||||
// system call requires root privileges. Drop ancillary groups regardless of
|
||||
// whether privileges are being dropped temporarily or permanently.
|
||||
//
|
||||
if(olduid == 0)
|
||||
setgroups(1, &newgid);
|
||||
|
||||
if(newgid != oldgid)
|
||||
{
|
||||
# if !defined(TIMEMORY_LINUX)
|
||||
auto ret = setegid(newgid);
|
||||
if(ret != 0)
|
||||
abort();
|
||||
if(permanent != 0 && setgid(newgid) == -1)
|
||||
abort();
|
||||
# else
|
||||
if(setregid((permanent ? newgid : oldgid), newgid) == -1)
|
||||
abort();
|
||||
# endif
|
||||
}
|
||||
|
||||
if(newuid != olduid)
|
||||
{
|
||||
# if !defined(TIMEMORY_LINUX)
|
||||
auto ret = seteuid(newuid);
|
||||
if(ret != 0)
|
||||
abort();
|
||||
if(permanent != 0 && setuid(newuid) == -1)
|
||||
abort();
|
||||
# else
|
||||
if(setreuid(((permanent != 0) ? newuid : olduid), newuid) == -1)
|
||||
abort();
|
||||
# endif
|
||||
}
|
||||
|
||||
// verify that the changes were successful
|
||||
if(permanent != 0)
|
||||
{
|
||||
if(newgid != oldgid && (setegid(oldgid) != -1 || getegid() != newgid))
|
||||
abort();
|
||||
if(newuid != olduid && (seteuid(olduid) != -1 || geteuid() != newuid))
|
||||
abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(newgid != oldgid && getegid() != newgid)
|
||||
abort();
|
||||
if(newuid != olduid && geteuid() != newuid)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
void
|
||||
restore_privileges()
|
||||
{
|
||||
if(geteuid() != get_group_info().user_id)
|
||||
if(seteuid(get_group_info().user_id) == -1 ||
|
||||
geteuid() != get_group_info().user_id)
|
||||
abort();
|
||||
if(getegid() != get_group_info().group_id)
|
||||
if(setegid(get_group_info().group_id) == -1 ||
|
||||
getegid() != get_group_info().group_id)
|
||||
abort();
|
||||
if(get_group_info().user_id == 0U)
|
||||
setgroups(get_group_info().ngroups, get_group_info().groups);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
int
|
||||
open_devnull(int fd)
|
||||
{
|
||||
FILE* f = nullptr;
|
||||
switch(fd)
|
||||
{
|
||||
case 0: f = freopen("/dev/null", "rb", stdin); break;
|
||||
case 1: f = freopen("/dev/null", "wb", stdout); break;
|
||||
case 2: f = freopen("/dev/null", "wb", stderr); break;
|
||||
default: break;
|
||||
}
|
||||
return (f != nullptr && fileno(f) == fd) ? 1 : 0;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
void
|
||||
sanitize_files()
|
||||
{
|
||||
// int fds;
|
||||
struct stat st;
|
||||
|
||||
// Make sure all open descriptors other than the standard ones are closed
|
||||
// if((fds = getdtablesize()) == -1)
|
||||
// fds = OPEN_MAX;
|
||||
|
||||
// closing these files results in the inability to read the pipe from the parent
|
||||
// for(int fd = 3; fd < fds; ++fd)
|
||||
// close(fd);
|
||||
|
||||
// Verify that the standard descriptors are open. If they're not, attempt to
|
||||
// open them using /dev/null. If any are unsuccessful, abort.
|
||||
for(int fd = 0; fd < 3; ++fd)
|
||||
{
|
||||
if(fstat(fd, &st) == -1 && (errno != EBADF || open_devnull(fd) == 0))
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
pid_t
|
||||
fork()
|
||||
{
|
||||
pid_t childpid;
|
||||
|
||||
if((childpid = ::fork()) == -1)
|
||||
return -1;
|
||||
|
||||
// If this is the parent process, there's nothing more to do
|
||||
if(childpid != 0)
|
||||
return childpid;
|
||||
|
||||
// This is the child process
|
||||
tim::popen::sanitize_files(); // Close all open files.
|
||||
tim::popen::drop_privileges(1); // Permanently drop privileges.
|
||||
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_PIPE*
|
||||
popen(const char* path, char** argv, char** envp)
|
||||
{
|
||||
int stdin_pipe[2] = { 0, 0 };
|
||||
int stdout_pipe[2] = { 0, 0 };
|
||||
TIMEMORY_PIPE* p = nullptr;
|
||||
|
||||
static char** _argv = []() {
|
||||
static auto _tmp = new char*[1];
|
||||
_tmp[0] = nullptr;
|
||||
return _tmp;
|
||||
}();
|
||||
|
||||
if(envp == nullptr)
|
||||
envp = environ;
|
||||
if(argv == nullptr)
|
||||
argv = _argv;
|
||||
|
||||
p = new TIMEMORY_PIPE;
|
||||
|
||||
if(!p)
|
||||
return nullptr;
|
||||
|
||||
p->read_fd = nullptr;
|
||||
p->write_fd = nullptr;
|
||||
p->child_pid = -1;
|
||||
|
||||
if(pipe(stdin_pipe) == -1)
|
||||
{
|
||||
delete p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(pipe(stdout_pipe) == -1)
|
||||
{
|
||||
close(stdin_pipe[1]);
|
||||
close(stdin_pipe[0]);
|
||||
delete p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!(p->read_fd = fdopen(stdout_pipe[0], "r")))
|
||||
{
|
||||
close(stdout_pipe[1]);
|
||||
close(stdout_pipe[0]);
|
||||
close(stdin_pipe[1]);
|
||||
close(stdin_pipe[0]);
|
||||
delete p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(!(p->write_fd = fdopen(stdin_pipe[1], "w")))
|
||||
{
|
||||
fclose(p->read_fd);
|
||||
close(stdout_pipe[1]);
|
||||
close(stdin_pipe[1]);
|
||||
close(stdin_pipe[0]);
|
||||
delete p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if((p->child_pid = tim::popen::fork()) == -1)
|
||||
{
|
||||
fclose(p->write_fd);
|
||||
fclose(p->read_fd);
|
||||
close(stdout_pipe[1]);
|
||||
close(stdin_pipe[0]);
|
||||
delete p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(p->child_pid == 0)
|
||||
{
|
||||
// this is the child process
|
||||
close(stdout_pipe[0]);
|
||||
close(stdin_pipe[1]);
|
||||
if(stdin_pipe[0] != 0)
|
||||
{
|
||||
dup2(stdin_pipe[0], 0);
|
||||
close(stdin_pipe[0]);
|
||||
}
|
||||
if(stdout_pipe[1] != 1)
|
||||
{
|
||||
dup2(stdout_pipe[1], 1);
|
||||
close(stdout_pipe[1]);
|
||||
}
|
||||
execve(path, argv, envp);
|
||||
exit(127);
|
||||
}
|
||||
|
||||
close(stdout_pipe[1]);
|
||||
close(stdin_pipe[0]);
|
||||
|
||||
return p;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
int
|
||||
pclose(TIMEMORY_PIPE* p)
|
||||
{
|
||||
int status = p->child_status;
|
||||
pid_t pid = -1;
|
||||
|
||||
// clean up memory
|
||||
auto _clean = [&]() {
|
||||
if(p->read_fd)
|
||||
fclose(p->read_fd);
|
||||
if(p->write_fd)
|
||||
fclose(p->write_fd);
|
||||
delete p;
|
||||
};
|
||||
|
||||
if(status != std::numeric_limits<int>::max())
|
||||
{
|
||||
_clean();
|
||||
if(WIFEXITED(status))
|
||||
{
|
||||
// printf("process %i exited, status=%d\n", p->child_pid,
|
||||
// WEXITSTATUS(status));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else if(WIFSIGNALED(status))
|
||||
{
|
||||
printf("process %i killed by signal %d\n", p->child_pid, WTERMSIG(status));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else if(WIFSTOPPED(status))
|
||||
{
|
||||
printf("process %i stopped by signal %d\n", p->child_pid, WSTOPSIG(status));
|
||||
// return EXIT_FAILURE;
|
||||
}
|
||||
else if(WIFCONTINUED(status))
|
||||
{
|
||||
printf("process %i continued\n", p->child_pid);
|
||||
// return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(p->child_pid != -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
pid = waitpid(p->child_pid, &status, 0);
|
||||
} while(pid == -1 && errno == EINTR);
|
||||
}
|
||||
}
|
||||
_clean();
|
||||
if(pid != -1 && WIFEXITED(status))
|
||||
return WEXITSTATUS(status);
|
||||
return (pid == -1 ? -1 : 0);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace popen
|
||||
} // namespace tim
|
||||
|
||||
#else
|
||||
|
||||
namespace
|
||||
{
|
||||
int windows_popen = 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1,241 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
#include "timemory/utility/utility.hpp"
|
||||
|
||||
#if !defined(TIMEMORY_WINDOWS)
|
||||
|
||||
# include <sstream>
|
||||
# include <string>
|
||||
# include <vector>
|
||||
|
||||
# include <cerrno>
|
||||
# include <cstdio>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
# include <ctime>
|
||||
# include <fcntl.h>
|
||||
# include <grp.h>
|
||||
# include <paths.h>
|
||||
# include <sys/param.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/wait.h>
|
||||
# include <unistd.h>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace popen
|
||||
{
|
||||
//
|
||||
using string_t = std::string;
|
||||
using strvec_t = std::vector<string_t>;
|
||||
//
|
||||
struct TIMEMORY_PIPE
|
||||
{
|
||||
FILE* read_fd = nullptr;
|
||||
FILE* write_fd = nullptr;
|
||||
pid_t child_pid;
|
||||
int child_status = std::numeric_limits<int>::max();
|
||||
};
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(TIMEMORY_PIPE*)
|
||||
popen(const char* path, char** argv = nullptr, char** envp = nullptr);
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(int)
|
||||
pclose(TIMEMORY_PIPE* p);
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(pid_t)
|
||||
fork();
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(void) // NOLINT
|
||||
sanitize_files();
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(int)
|
||||
open_devnull(int fd);
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(void)
|
||||
drop_privileges(int permanent);
|
||||
//
|
||||
TIMEMORY_UTILITY_LINKAGE(void) // NOLINT
|
||||
restore_privileges();
|
||||
//
|
||||
inline strvec_t
|
||||
read_fork(TIMEMORY_PIPE* proc, int max_counter = 50)
|
||||
{
|
||||
int counter = 0;
|
||||
strvec_t linked_libraries;
|
||||
|
||||
while(proc)
|
||||
{
|
||||
char buffer[4096];
|
||||
auto* ret = fgets(buffer, 4096, proc->read_fd);
|
||||
if(ret == nullptr || strlen(buffer) == 0)
|
||||
{
|
||||
if(max_counter == 0)
|
||||
{
|
||||
pid_t cpid = waitpid(proc->child_pid, &proc->child_status, WNOHANG);
|
||||
if(cpid == 0)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(counter++ > max_counter)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
auto line = string_t(buffer);
|
||||
auto loc = string_t::npos;
|
||||
while((loc = line.find_first_of("\n\t")) != string_t::npos)
|
||||
line.erase(loc, 1);
|
||||
auto delim = delimit(line, " \n\t=>");
|
||||
for(const auto& itr : delim)
|
||||
{
|
||||
if(itr.find('/') == 0)
|
||||
linked_libraries.push_back(itr);
|
||||
}
|
||||
}
|
||||
|
||||
return linked_libraries;
|
||||
}
|
||||
//
|
||||
inline std::ostream&
|
||||
flush_output(std::ostream& os, TIMEMORY_PIPE* proc, int max_counter = 0)
|
||||
{
|
||||
int counter = 0;
|
||||
while(proc)
|
||||
{
|
||||
char buffer[4096];
|
||||
auto* ret = fgets(buffer, 4096, proc->read_fd);
|
||||
if(ret == nullptr || strlen(buffer) == 0)
|
||||
{
|
||||
if(max_counter == 0)
|
||||
{
|
||||
pid_t cpid = waitpid(proc->child_pid, &proc->child_status, WNOHANG);
|
||||
if(cpid == 0)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(counter++ > max_counter)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
os << string_t{ buffer } << std::flush;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace popen
|
||||
} // namespace tim
|
||||
|
||||
# if !defined(TIMEMORY_UTILITY_SOURCE) && !defined(TIMEMORY_USE_UTILITY_EXTERN)
|
||||
# include "timemory/utility/popen.cpp"
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
inline bool
|
||||
launch_process(const char* cmd, const std::string& extra, std::ostream* os)
|
||||
{
|
||||
#if !defined(TIMEMORY_WINDOWS)
|
||||
auto delim = tim::delimit(cmd, " \t");
|
||||
tim::popen::TIMEMORY_PIPE* fp = nullptr;
|
||||
if(delim.size() < 2)
|
||||
{
|
||||
fp = tim::popen::popen(cmd, nullptr, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
static std::string _c = "-c";
|
||||
std::array<char*, 4> _args;
|
||||
_args.fill(nullptr);
|
||||
char* _cshell = getenv("SHELL");
|
||||
char* _ushell = getusershell();
|
||||
std::string _shell = (_cshell) ? _cshell : (_ushell) ? getusershell() : "/bin/sh";
|
||||
_args.at(0) = (char*) _shell.c_str();
|
||||
_args.at(1) = (char*) _c.c_str();
|
||||
_args.at(2) = (char*) cmd;
|
||||
fp = tim::popen::popen(_args.at(0), _args.data());
|
||||
}
|
||||
|
||||
if(fp == nullptr)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[timemory]> Error launching command: '" << cmd << "'... " << extra;
|
||||
perror(ss.str().c_str());
|
||||
return false;
|
||||
}
|
||||
if(os)
|
||||
{
|
||||
popen::flush_output(*os, fp);
|
||||
}
|
||||
|
||||
auto ec = tim::popen::pclose(fp);
|
||||
if(ec != 0)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[timemory]> Command: '" << cmd << "' returned a non-zero exit code: " << ec
|
||||
<< "... " << extra;
|
||||
perror(ss.str().c_str());
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if(std::system(nullptr) != 0)
|
||||
{
|
||||
int ec = std::system(cmd);
|
||||
|
||||
if(ec != 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[timemory]> Command: '%s' returned a non-zero exit code: %i... %s\n",
|
||||
cmd, ec, extra.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "std::system unavailable for command: '%s'... %s\n", cmd,
|
||||
extra.c_str());
|
||||
return false;
|
||||
}
|
||||
(void) os;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace tim
|
||||
@@ -1,142 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
// For std::decay
|
||||
#include <type_traits>
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
template <typename>
|
||||
struct transient_function; // intentionally not defined
|
||||
|
||||
/// \struct tim::utility::transient_function
|
||||
/// \brief A light-weight alternative to std::function. Pass any callback - including
|
||||
/// capturing lambdas - cheaply and quickly as a function argument
|
||||
///
|
||||
/// - No instantiation of called function at each call site
|
||||
/// - Simple to use - use transient_function<...> as the function argument
|
||||
/// - Low cost, cheap setup, one indirect function call to invoke
|
||||
/// - No risk of dynamic allocation (unlike std::function)
|
||||
/// - Not persistent: synchronous calls only
|
||||
///
|
||||
template <typename RetT, typename... Args>
|
||||
struct transient_function<RetT(Args...)>
|
||||
{
|
||||
using dispatch_type = RetT (*)(void*, Args...);
|
||||
using target_function_reference = RetT(Args...);
|
||||
|
||||
// dispatch_type() is instantiated by the transient_function constructor,
|
||||
// which will store a pointer to the function in m_dispatch.
|
||||
template <typename Up>
|
||||
static RetT dispatcher(void* target, Args&&... args)
|
||||
{
|
||||
return (*static_cast<Up*>(target))(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
transient_function() = default;
|
||||
~transient_function() = default;
|
||||
transient_function(transient_function&&) noexcept = default;
|
||||
transient_function& operator=(transient_function&&) noexcept = default;
|
||||
|
||||
template <typename Tp>
|
||||
transient_function(Tp&& target)
|
||||
: m_dispatch(&dispatcher<std::decay_t<Tp>>)
|
||||
, m_target(&target)
|
||||
{}
|
||||
|
||||
// Specialize for reference-to-function, to ensure that a valid pointer is stored.
|
||||
transient_function(target_function_reference target)
|
||||
: m_dispatch(dispatcher<target_function_reference>)
|
||||
{
|
||||
static_assert(
|
||||
sizeof(void*) == sizeof(target),
|
||||
"It will not be possible to pass functions by reference on this platform. "
|
||||
"Please use explicit function pointers i.e. foo(target) -> foo(&target)");
|
||||
m_target = static_cast<void*>(target);
|
||||
}
|
||||
|
||||
// Specialize for reference-to-function, to ensure that a valid pointer is stored.
|
||||
transient_function& operator=(target_function_reference target)
|
||||
{
|
||||
if(this == &target)
|
||||
return *this;
|
||||
|
||||
static_assert(
|
||||
sizeof(void*) == sizeof(target),
|
||||
"It will not be possible to pass functions by reference on this platform. "
|
||||
"Please use explicit function pointers i.e. foo(target) -> foo(&target)");
|
||||
m_dispatch = dispatcher<target_function_reference>;
|
||||
m_target = static_cast<void*>(target);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RetT operator()(Args&&... args) const
|
||||
{
|
||||
return m_dispatch(m_target, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
// A pointer to the static function that will call the wrapped invokable object
|
||||
dispatch_type m_dispatch = nullptr;
|
||||
void* m_target = nullptr; // pointer to the invokable object
|
||||
};
|
||||
//
|
||||
} // namespace utility
|
||||
//
|
||||
namespace scope
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::scope::destructor
|
||||
/// \brief provides an object which can be returned from functions that will execute
|
||||
/// the lambda provided during construction when it is destroyed
|
||||
///
|
||||
struct transient_destructor
|
||||
{
|
||||
template <typename FuncT>
|
||||
transient_destructor(FuncT&& _func)
|
||||
: m_functor(std::forward<FuncT>(_func))
|
||||
{}
|
||||
|
||||
// delete copy operations
|
||||
transient_destructor(const transient_destructor&) = delete;
|
||||
transient_destructor& operator=(const transient_destructor&) = delete;
|
||||
|
||||
// allow move operations
|
||||
transient_destructor(transient_destructor&& rhs) noexcept = default;
|
||||
transient_destructor& operator=(transient_destructor&& rhs) noexcept = default;
|
||||
|
||||
~transient_destructor() { m_functor(); }
|
||||
|
||||
private:
|
||||
utility::transient_function<void()> m_functor = []() {};
|
||||
};
|
||||
} // namespace scope
|
||||
//
|
||||
} // namespace tim
|
||||
@@ -1,846 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \file timemory/utility/types.hpp
|
||||
* \headerfile timemory/utility/types.hpp "timemory/utility/types.hpp"
|
||||
* Declaration of types for utility directory
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/compat/macros.h"
|
||||
#include "timemory/hash/types.hpp"
|
||||
#include "timemory/macros/attributes.hpp"
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/mpl/concepts.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_FOLD_EXPRESSION)
|
||||
# if defined(CXX17)
|
||||
# define TIMEMORY_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
# else
|
||||
# define TIMEMORY_FOLD_EXPRESSION(...) \
|
||||
::tim::consume_parameters(::std::initializer_list<int>{ (__VA_ARGS__, 0)... })
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_FOLD_EXPANSION)
|
||||
# define TIMEMORY_FOLD_EXPANSION(TYPE, SIZE, ...) \
|
||||
std::array<TYPE, SIZE>({ (::tim::consume_parameters(), __VA_ARGS__)... });
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_RETURN_FOLD_EXPRESSION)
|
||||
# define TIMEMORY_RETURN_FOLD_EXPRESSION(...) \
|
||||
::std::make_tuple((::tim::consume_parameters(), __VA_ARGS__)...)
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DECLARE_EXTERN_TEMPLATE)
|
||||
# define TIMEMORY_DECLARE_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE)
|
||||
# define TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE(...) template __VA_ARGS__;
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_ESC)
|
||||
# define TIMEMORY_ESC(...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DELETED_OBJECT)
|
||||
# define TIMEMORY_DELETED_OBJECT(NAME) \
|
||||
NAME() = delete; \
|
||||
NAME(const NAME&) = delete; \
|
||||
NAME(NAME&&) = delete; \
|
||||
NAME& operator=(const NAME&) = delete; \
|
||||
NAME& operator=(NAME&&) = delete;
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DELETE_COPY_MOVE_OBJECT)
|
||||
# define TIMEMORY_DELETE_COPY_MOVE_OBJECT(NAME) \
|
||||
NAME(const NAME&) = delete; \
|
||||
NAME(NAME&&) = delete; \
|
||||
NAME& operator=(const NAME&) = delete; \
|
||||
NAME& operator=(NAME&&) = delete;
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DEFAULT_MOVE_ONLY_OBJECT)
|
||||
# define TIMEMORY_DEFAULT_MOVE_ONLY_OBJECT(NAME) \
|
||||
NAME(const NAME&) = delete; \
|
||||
NAME(NAME&&) noexcept = default; \
|
||||
NAME& operator=(const NAME&) = delete; \
|
||||
NAME& operator=(NAME&&) noexcept = default;
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_DEFAULT_OBJECT)
|
||||
# define TIMEMORY_DEFAULT_OBJECT(NAME) \
|
||||
TIMEMORY_HOST_DEVICE_FUNCTION NAME() = default; \
|
||||
NAME(const NAME&) = default; \
|
||||
NAME(NAME&&) noexcept = default; \
|
||||
NAME& operator=(const NAME&) = default; \
|
||||
NAME& operator=(NAME&&) noexcept = default;
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_EXCEPTION)
|
||||
# define TIMEMORY_EXCEPTION(...) \
|
||||
{ \
|
||||
std::stringstream _errmsg; \
|
||||
_errmsg << __VA_ARGS__; \
|
||||
perror(_errmsg.str().c_str()); \
|
||||
std::cerr << _errmsg.str() << std::endl; \
|
||||
std::exit(EXIT_FAILURE); \
|
||||
}
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_TESTING_EXCEPTION) && defined(TIMEMORY_INTERNAL_TESTING)
|
||||
# define TIMEMORY_TESTING_EXCEPTION(...) \
|
||||
{ \
|
||||
TIMEMORY_EXCEPTION(__VA_ARGS__) \
|
||||
}
|
||||
#elif !defined(TIMEMORY_TESTING_EXCEPTION)
|
||||
# define TIMEMORY_TESTING_EXCEPTION(...) \
|
||||
{}
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
#if !defined(TIMEMORY_TUPLE_ACCESSOR)
|
||||
# define TIMEMORY_TUPLE_ACCESSOR(INDEX, TUPLE, NAME) \
|
||||
auto& NAME() { return std::get<INDEX>(TUPLE); } \
|
||||
const auto& NAME() const { return std::get<INDEX>(TUPLE); }
|
||||
#endif
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
/// Alias template make_integer_sequence
|
||||
template <typename Tp, Tp Num>
|
||||
using make_integer_sequence = std::make_integer_sequence<Tp, Num>;
|
||||
//
|
||||
/// Alias template index_sequence
|
||||
template <size_t... Idx>
|
||||
using index_sequence = std::integer_sequence<size_t, Idx...>;
|
||||
//
|
||||
/// Alias template make_index_sequence
|
||||
template <size_t Num>
|
||||
using make_index_sequence = std::make_integer_sequence<size_t, Num>;
|
||||
//
|
||||
/// Alias template index_sequence_for
|
||||
template <typename... Types>
|
||||
using index_sequence_for = std::make_index_sequence<sizeof...(Types)>;
|
||||
//
|
||||
/// Alias template for enable_if
|
||||
template <bool B, typename T = int>
|
||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
//
|
||||
/// Alias template for decay
|
||||
template <typename T>
|
||||
using decay_t = typename std::decay<T>::type;
|
||||
//
|
||||
template <bool B, typename Lhs, typename Rhs>
|
||||
using conditional_t = typename std::conditional<B, Lhs, Rhs>::type;
|
||||
//
|
||||
template <typename T>
|
||||
using remove_cv_t = typename std::remove_cv<T>::type;
|
||||
//
|
||||
template <typename T>
|
||||
using remove_const_t = typename std::remove_const<T>::type;
|
||||
//
|
||||
template <int N>
|
||||
using priority_constant = std::integral_constant<int, N>;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename T>
|
||||
struct identity
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
//
|
||||
template <typename T>
|
||||
using identity_t = typename identity<T>::type;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::null_type
|
||||
/// \brief this is a placeholder type for optional type-traits. It is used as the default
|
||||
/// type for the type-traits to signify there is no specialization.
|
||||
struct null_type : concepts::null_type
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::type_list
|
||||
/// \brief lightweight tuple-alternative for meta-programming logic
|
||||
template <typename... Tp>
|
||||
struct type_list
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::type_list_element
|
||||
/// \brief Variant of `std::tuple_element` for \ref tim::type_list
|
||||
template <size_t Idx, typename Tp>
|
||||
struct type_list_element;
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template <size_t Idx, size_t TargIdx, typename... Tail>
|
||||
struct type_list_element;
|
||||
|
||||
template <size_t Idx, size_t TargIdx>
|
||||
struct type_list_element<Idx, TargIdx>
|
||||
{
|
||||
using type = tim::null_type;
|
||||
// TargIdx will be equal to Idx + 1 in second half of conditional statement
|
||||
// below. If the second half of that conditional statement is entered, the
|
||||
// following static_assert will be true
|
||||
static_assert(TargIdx < Idx + 2, "Error! Index exceeded size of of type_list");
|
||||
};
|
||||
|
||||
template <size_t Idx, size_t TargIdx, typename Tp, typename... Tail>
|
||||
struct type_list_element<Idx, TargIdx, Tp, Tail...>
|
||||
{
|
||||
using type =
|
||||
conditional_t<Idx == TargIdx, Tp,
|
||||
typename type_list_element<Idx + 1, TargIdx, Tail...>::type>;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <size_t Idx, typename... Types>
|
||||
struct type_list_element<Idx, type_list<Types...>>
|
||||
{
|
||||
using type = typename internal::type_list_element<0, Idx, Types...>::type;
|
||||
};
|
||||
|
||||
template <size_t Idx, typename Tp>
|
||||
using type_list_element_t = typename type_list_element<Idx, Tp>::type;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \fn tim::consume_parameters
|
||||
/// \brief use this function to get rid of "unused parameter" warnings
|
||||
template <typename... ArgsT>
|
||||
TIMEMORY_ALWAYS_INLINE void
|
||||
consume_parameters(ArgsT&&...) TIMEMORY_HIDDEN TIMEMORY_NEVER_INSTRUMENT;
|
||||
//
|
||||
template <typename... ArgsT>
|
||||
void
|
||||
consume_parameters(ArgsT&&...)
|
||||
{}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Tp, typename DeleterT, typename Tag>
|
||||
class singleton;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace cupti
|
||||
{
|
||||
struct result;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace crtp
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::crtp::base
|
||||
/// \brief a generic type for prioritizing a function call to the base class over
|
||||
/// derived functions, e.g. void start(crtp::base, Args&&... args) { start(args...); }
|
||||
struct base
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace crtp
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace mpl
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::mpl::lightweight
|
||||
/// \brief a generic type for indicating that function call or constructor should be
|
||||
/// as lightweight as possible.
|
||||
struct lightweight
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename... Tp>
|
||||
struct piecewise_select
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace mpl
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace scope
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::scope::tree
|
||||
/// \brief Dummy struct to designates tree (hierarchical) storage. This scope (default)
|
||||
/// maintains nesting in the call-graph storage. In this scoping mode, the results
|
||||
/// will be separated from each other based on the identifier AND the current number
|
||||
/// of component instances in a "start" region. E.g. for two components with the
|
||||
/// same identifiers where the first calls start, then the second calls start then
|
||||
/// the second will be at a depth of +1 relative to the first (i.e. a child of the first).
|
||||
struct tree : std::integral_constant<int, 2>
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::scope::flat
|
||||
/// \brief Dummy struct to designates flat (no hierarchy) storage.
|
||||
/// When flat scoping is globally enabled, all entries to the call-graph storage at
|
||||
/// entered at a depth of zero. Thus, if you want a report of all the function calls
|
||||
/// and their total values for each identifier, flat scoping should be globally enabled.
|
||||
/// This can be combined with timeline scoping to produce results where every measurement
|
||||
/// is its own call-graph entry at a depth of zero (produces a large amount of data).
|
||||
/// Flat-scoping can be enabled at the component bundler level also, there are two
|
||||
/// ways to do this: (1) to enable flat-scoping for all instances of the bundle, add \ref
|
||||
/// tim::quirk::flat_scope to the template parameters of the bundler; (2) to enable
|
||||
/// flat-scoping for specific bundler instances, pass \code{.cpp}
|
||||
/// tim::quirk::config<tim::quirk::flat_scope, ...>{} \endcode as the second argument to
|
||||
/// the constructor of the bundle.
|
||||
struct flat : std::integral_constant<int, 0>
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::scope::timeline
|
||||
/// \brief Dummy struct to designates timeline (hierarchical, non-duplicated) storage.
|
||||
/// It is meaningless by itself and should be combined with \ref tim::scope::tree or
|
||||
/// \ref tim::scope::flat. A tree timeline has all the hierarchy properties of the
|
||||
/// tree scope but entries at the same depth with the same identifiers are separated
|
||||
/// entries in the resuls.
|
||||
/// Timeline-scoping can be enabled at the component bundler level also, there are two
|
||||
/// ways to do this: (1) to enable timeline-scoping for all instances of the bundle, add
|
||||
/// \ref tim::quirk::timeline_scope to the template parameters of the bundler; (2) to
|
||||
/// enable timeline-scoping for specific bundler instances, pass \code{.cpp}
|
||||
/// tim::quirk::config<tim::quirk::timeline_scope, ...>{} \endcode as the second argument
|
||||
/// to the constructor of the bundle.
|
||||
struct timeline : std::integral_constant<int, 1>
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
static constexpr size_t scope_count = 3;
|
||||
using data_type = std::bitset<scope_count>;
|
||||
using input_type = std::array<bool, scope_count>;
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
inline input_type&
|
||||
get_fields()
|
||||
{
|
||||
static input_type _instance{ { false, false, false } };
|
||||
return _instance;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <typename Arg, size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE auto
|
||||
generate(Arg&& arg, index_sequence<Idx...>)
|
||||
{
|
||||
static_assert(sizeof...(Idx) <= scope_count, "Error! Bad index sequence size");
|
||||
data_type ret;
|
||||
TIMEMORY_FOLD_EXPRESSION(ret.set(Idx, arg[Idx]));
|
||||
return ret;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t... Idx>
|
||||
static TIMEMORY_HOT_INLINE auto
|
||||
either(data_type ret, data_type arg, index_sequence<Idx...>)
|
||||
{
|
||||
static_assert(sizeof...(Idx) <= scope_count, "Error! Bad index sequence size");
|
||||
TIMEMORY_FOLD_EXPRESSION(ret.set(Idx, ret.test(Idx) || arg.test(Idx)));
|
||||
return ret;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
static TIMEMORY_HOT_INLINE auto
|
||||
get_default_bitset() -> data_type
|
||||
{
|
||||
return generate(get_fields(), make_index_sequence<scope_count>{});
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \struct tim::scope::config
|
||||
/// \brief this data type encodes the options of storage scope. The default is
|
||||
/// hierarchical (tree) scope. Specification of flat scope overrides the hierarchy
|
||||
/// scope, e.g. you cannot have a hierarchical flat scope. The timeline scope
|
||||
/// is meaningless should a specification of tree or flat, thus the valid combinations
|
||||
/// are: tree, flat, tree + timeline, flat + timeline.
|
||||
struct config : public data_type
|
||||
{
|
||||
config()
|
||||
: data_type(get_default_bitset())
|
||||
{}
|
||||
|
||||
explicit config(const data_type& obj)
|
||||
: data_type(obj)
|
||||
{}
|
||||
|
||||
explicit config(data_type&& obj) noexcept
|
||||
: data_type(std::forward<data_type>(obj))
|
||||
{}
|
||||
|
||||
explicit config(bool _flat)
|
||||
: data_type(generate(input_type{ { _flat, false, false } },
|
||||
make_index_sequence<scope_count>{}))
|
||||
{}
|
||||
|
||||
explicit config(bool _flat, bool _timeline)
|
||||
: data_type(generate(input_type{ { _flat, _timeline, false } },
|
||||
make_index_sequence<scope_count>{}))
|
||||
{}
|
||||
|
||||
explicit config(bool _flat, bool _timeline, bool _tree)
|
||||
: data_type(generate(input_type{ { _flat, _timeline, _tree } },
|
||||
make_index_sequence<scope_count>{}))
|
||||
{}
|
||||
|
||||
config(tree)
|
||||
: config(false, false, false)
|
||||
{}
|
||||
|
||||
config(flat)
|
||||
: config(true, false, false)
|
||||
{}
|
||||
|
||||
config(timeline)
|
||||
: config(false, true, false)
|
||||
{}
|
||||
|
||||
template <typename Arg, typename... Args,
|
||||
std::enable_if_t<(std::is_same<Arg, tree>::value ||
|
||||
std::is_same<Arg, flat>::value ||
|
||||
std::is_same<Arg, timeline>::value),
|
||||
int> = 0>
|
||||
explicit config(Arg&& arg, Args&&... args)
|
||||
{
|
||||
*this += std::forward<Arg>(arg);
|
||||
TIMEMORY_FOLD_EXPRESSION(*this += std::forward<Args>(args));
|
||||
}
|
||||
|
||||
~config() = default;
|
||||
config(const config&) = default;
|
||||
config(config&&) noexcept = default;
|
||||
config& operator=(const config&) = default;
|
||||
config& operator=(config&&) noexcept = default;
|
||||
|
||||
config& operator=(const data_type& rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
data_type::operator=(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
config& operator=(data_type&& rhs) noexcept
|
||||
{
|
||||
if(this != &rhs)
|
||||
data_type::operator=(std::forward<data_type>(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<(std::is_same<T, tree>::value ||
|
||||
std::is_same<T, flat>::value ||
|
||||
std::is_same<T, timeline>::value),
|
||||
int> = 0>
|
||||
config& operator+=(T)
|
||||
{
|
||||
this->data_type::set(T::value, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
using data_type::set;
|
||||
|
||||
template <typename T, std::enable_if_t<(std::is_same<T, tree>::value ||
|
||||
std::is_same<T, flat>::value ||
|
||||
std::is_same<T, timeline>::value),
|
||||
int> = 0>
|
||||
config& set(bool val = true)
|
||||
{
|
||||
this->data_type::set(T::value, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TIMEMORY_NODISCARD bool is_flat() const { return this->test(flat::value); }
|
||||
TIMEMORY_NODISCARD bool is_timeline() const { return this->test(timeline::value); }
|
||||
// "tree" is default behavior so it returns true if nothing is set but gives
|
||||
// priority to the flat setting
|
||||
TIMEMORY_NODISCARD bool is_tree() const
|
||||
{
|
||||
return this->none() || (this->test(tree::value) && !this->test(flat::value));
|
||||
}
|
||||
TIMEMORY_NODISCARD bool is_flat_timeline() const
|
||||
{
|
||||
return (is_flat() && is_timeline());
|
||||
}
|
||||
TIMEMORY_NODISCARD bool is_tree_timeline() const
|
||||
{
|
||||
return (is_tree() && is_timeline());
|
||||
}
|
||||
|
||||
template <bool ForceFlatT>
|
||||
TIMEMORY_NODISCARD bool is_flat() const
|
||||
{
|
||||
return (ForceFlatT) ? true : this->test(flat::value);
|
||||
}
|
||||
|
||||
template <bool ForceTreeT, bool ForceTimeT>
|
||||
TIMEMORY_NODISCARD bool is_tree() const
|
||||
{
|
||||
return (ForceTreeT)
|
||||
? true
|
||||
: ((ForceTimeT) ? false
|
||||
: (this->none() || (this->test(tree::value) &&
|
||||
!this->test(flat::value))));
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const config& obj)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::boolalpha << "tree: " << obj.is_tree() << ", flat: " << obj.is_flat()
|
||||
<< ", timeline: " << obj.is_timeline()
|
||||
<< ". Values: flat::value = " << obj.test(flat::value)
|
||||
<< ", timeline::value = " << obj.test(timeline::value)
|
||||
<< ", tree::value = " << obj.test(tree::value);
|
||||
os << ss.str();
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename ForceTreeT = false_type, typename ForceFlatT = false_type,
|
||||
typename ForceTimeT = false_type>
|
||||
uint64_t compute_depth(uint64_t _current)
|
||||
{
|
||||
static_assert(!(ForceTreeT::value && ForceFlatT::value),
|
||||
"Error! Type cannot enforce tree-based call-stack depth storage "
|
||||
"and flat call-stack depth storage simulatenously");
|
||||
// flat: always at depth of 1
|
||||
// tree: features nesting
|
||||
// timeline: features nesting if not flat and depth of 1 if flat
|
||||
if(ForceFlatT::value || is_flat())
|
||||
{
|
||||
// flat + timeline will be differentiated via compute_hash
|
||||
// flat + tree is invalid and flat takes precedence
|
||||
// printf("compute_depth is flat at %i\n", (int) _current);
|
||||
return 1;
|
||||
}
|
||||
// if not flat, return the nested depth and compute_hash will account
|
||||
// for whether the entry is a duplicate or not
|
||||
// printf("compute_depth is tree or timeline at %i\n", (int) _current);
|
||||
return _current + 1;
|
||||
}
|
||||
|
||||
template <typename ForceTreeT = false_type, typename ForceFlatT = false_type,
|
||||
typename ForceTimeT = false_type>
|
||||
uint64_t compute_hash(uint64_t _id, uint64_t _depth, uint64_t& _counter)
|
||||
{
|
||||
// flat/tree: always compute the same hash for a given depth and key
|
||||
// timeline: uses a counter to differentiate idential hashes occurring at diff
|
||||
// time points.
|
||||
// below is a fall-through (i.e. not an if-else) bc either tree or flat can be
|
||||
// combined with timeline but in the case of tree + flat, flat will take
|
||||
// precedence.
|
||||
if(is_tree<ForceTreeT::value, ForceTimeT::value>() ||
|
||||
is_flat<ForceFlatT::value>())
|
||||
{
|
||||
// printf("compute_hash is tree or flat at %i\n", (int) _depth);
|
||||
_id = get_combined_hash_id(_id, _depth);
|
||||
// _id ^= _depth;
|
||||
}
|
||||
if(ForceTimeT::value || is_timeline())
|
||||
{
|
||||
// printf("compute_hash is timeline at %i\n", (int) _depth);
|
||||
_id = get_combined_hash_id(_id, _counter++);
|
||||
// _id ^= _counter++;
|
||||
}
|
||||
// printf("compute_hash is %i at depth %i (counter = %i)\n", (int) _id, (int)
|
||||
// _depth,
|
||||
// (int) _counter);
|
||||
return _id;
|
||||
}
|
||||
};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// clang-format off
|
||||
static TIMEMORY_INLINE config
|
||||
get_default() TIMEMORY_HOT;
|
||||
TIMEMORY_INLINE config
|
||||
operator+(config _lhs, tree) TIMEMORY_HOT;
|
||||
TIMEMORY_INLINE config
|
||||
operator+(config _lhs, flat) TIMEMORY_HOT;
|
||||
TIMEMORY_INLINE config
|
||||
operator+(config _lhs, timeline) TIMEMORY_HOT;
|
||||
TIMEMORY_INLINE config
|
||||
operator+(config _lhs, config _rhs) TIMEMORY_HOT;
|
||||
// clang-format on
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
static TIMEMORY_HOT_INLINE auto
|
||||
get_default() -> config
|
||||
{
|
||||
return config{ get_default_bitset() };
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_HOT_INLINE auto
|
||||
operator+(config _lhs, tree) -> config
|
||||
{
|
||||
_lhs.set(tree::value, true);
|
||||
return _lhs;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_HOT_INLINE auto
|
||||
operator+(config _lhs, flat) -> config
|
||||
{
|
||||
_lhs.set(flat::value, true);
|
||||
return _lhs;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_HOT_INLINE auto
|
||||
operator+(config _lhs, timeline) -> config
|
||||
{
|
||||
_lhs.set(timeline::value, true);
|
||||
return _lhs;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_HOT_INLINE auto
|
||||
operator+(config _lhs, config _rhs) -> config
|
||||
{
|
||||
return config{ either(_lhs, _rhs, make_index_sequence<scope_count>{}) };
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::scope::destructor
|
||||
/// \brief provides an object which can be returned from functions that will execute
|
||||
/// the lambda provided during construction when it is destroyed
|
||||
///
|
||||
struct destructor
|
||||
{
|
||||
template <typename FuncT>
|
||||
destructor(FuncT&& _func)
|
||||
: m_functor(std::forward<FuncT>(_func))
|
||||
{}
|
||||
|
||||
// delete copy operations
|
||||
destructor(const destructor&) = delete;
|
||||
destructor& operator=(const destructor&) = delete;
|
||||
|
||||
// allow move operations
|
||||
destructor(destructor&& rhs) noexcept
|
||||
: m_functor(std::move(rhs.m_functor))
|
||||
{
|
||||
rhs.m_functor = []() {};
|
||||
}
|
||||
|
||||
destructor& operator=(destructor&& rhs) noexcept
|
||||
{
|
||||
if(this != &rhs)
|
||||
{
|
||||
m_functor = std::move(rhs.m_functor);
|
||||
rhs.m_functor = []() {};
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~destructor() { m_functor(); }
|
||||
|
||||
private:
|
||||
std::function<void()> m_functor = []() {};
|
||||
};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace scope
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace lifetime
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::lifetime::scoped
|
||||
/// \brief Dummy struct for meta-programming to designate that a component activates
|
||||
/// it's features at the first start() invocation and deactivates it's features when
|
||||
/// all instances that called start() have called stop(). Thus, the component's
|
||||
/// features are dependent on at least one component instance existing in memory
|
||||
/// (excluding the instances in the call-graph, which never call start/stop)
|
||||
///
|
||||
struct scoped
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::lifetime::persistent
|
||||
/// \brief Dummy struct for meta-programming to designate that a component activates its
|
||||
/// features in {global,thread}_init and deactivates it's features in
|
||||
/// {global,thead}_finalize
|
||||
///
|
||||
struct persistent
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace lifetime
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
namespace audit
|
||||
{
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::audit::incoming
|
||||
/// \brief Used by component audit member function to designate the
|
||||
/// parameters being passed are incoming (e.g. before a gotcha wrappee is invoked)
|
||||
///
|
||||
struct incoming : concepts::phase_id
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
/// \struct tim::audit::outgoing
|
||||
/// \brief Used by component audit member function to designate the
|
||||
/// parameters being passed are outgoing (e.g. the return value from a gotcha wrappee)
|
||||
///
|
||||
// audit the return type
|
||||
struct outgoing : concepts::phase_id
|
||||
{};
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
} // namespace audit
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace tim
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <size_t Idx, typename... Types>
|
||||
struct tuple_element<Idx, tim::type_list<Types...>>
|
||||
{
|
||||
using type = typename tim::type_list_element<Idx, tim::type_list<Types...>>::type;
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
namespace tim
|
||||
{
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <typename Tp>
|
||||
struct StaticVersion;
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
} // namespace tim
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if !defined(TIMEMORY_SET_CLASS_VERSION)
|
||||
# define TIMEMORY_SET_CLASS_VERSION(VERSION_NUMBER, ...) \
|
||||
namespace tim \
|
||||
{ \
|
||||
namespace cereal \
|
||||
{ \
|
||||
namespace detail \
|
||||
{ \
|
||||
template <> \
|
||||
struct StaticVersion<__VA_ARGS__> \
|
||||
{ \
|
||||
static constexpr std::uint32_t version = VERSION_NUMBER; \
|
||||
}; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TIMEMORY_GET_CLASS_VERSION)
|
||||
# define TIMEMORY_GET_CLASS_VERSION(...) \
|
||||
::tim::cereal::detail::StaticVersion<__VA_ARGS__>::version
|
||||
#endif
|
||||
@@ -1,409 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef TIMEMORY_UTILITY_UTILITY_CPP_
|
||||
#define TIMEMORY_UTILITY_UTILITY_CPP_ 1
|
||||
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
|
||||
#if !defined(TIMEMORY_UTILITY_HEADER_MODE)
|
||||
# include "timemory/utility/utility.hpp"
|
||||
#endif
|
||||
|
||||
namespace tim
|
||||
{
|
||||
//
|
||||
std::string
|
||||
dirname(std::string _fname)
|
||||
{
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
char* _cfname = realpath(_fname.c_str(), nullptr);
|
||||
_fname = std::string(_cfname);
|
||||
free(_cfname);
|
||||
|
||||
while(_fname.find("\\\\") != std::string::npos)
|
||||
_fname.replace(_fname.find("\\\\"), 2, "/");
|
||||
while(_fname.find('\\') != std::string::npos)
|
||||
_fname.replace(_fname.find('\\'), 1, "/");
|
||||
|
||||
return _fname.substr(0, _fname.find_last_of('/'));
|
||||
#elif defined(TIMEMORY_WINDOWS)
|
||||
while(_fname.find('/') != std::string::npos)
|
||||
_fname.replace(_fname.find('/'), 1, "\\");
|
||||
|
||||
_fname = _fname.substr(0, _fname.find_last_of('\\'));
|
||||
return (_fname.at(_fname.length() - 1) == '\\')
|
||||
? _fname.substr(0, _fname.length() - 1)
|
||||
: _fname;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
int
|
||||
makedir(std::string _dir, int umask)
|
||||
{
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
while(_dir.find("\\\\") != std::string::npos)
|
||||
_dir.replace(_dir.find("\\\\"), 2, "/");
|
||||
while(_dir.find('\\') != std::string::npos)
|
||||
_dir.replace(_dir.find('\\'), 1, "/");
|
||||
|
||||
if(_dir.length() == 0)
|
||||
return 0;
|
||||
|
||||
int ret = mkdir(_dir.c_str(), umask);
|
||||
if(ret != 0)
|
||||
{
|
||||
int err = errno;
|
||||
if(err != EEXIST)
|
||||
{
|
||||
std::cerr << "mkdir(" << _dir.c_str() << ", " << umask
|
||||
<< ") returned: " << ret << std::endl;
|
||||
std::stringstream _sdir;
|
||||
_sdir << "/bin/mkdir -p " << _dir;
|
||||
return (launch_process(_sdir.str().c_str())) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
#elif defined(TIMEMORY_WINDOWS)
|
||||
consume_parameters(umask);
|
||||
while(_dir.find('/') != std::string::npos)
|
||||
_dir.replace(_dir.find('/'), 1, "\\");
|
||||
|
||||
if(_dir.length() == 0)
|
||||
return 0;
|
||||
|
||||
int ret = _mkdir(_dir.c_str());
|
||||
if(ret != 0)
|
||||
{
|
||||
int err = errno;
|
||||
if(err != EEXIST)
|
||||
{
|
||||
std::cerr << "_mkdir(" << _dir.c_str() << ") returned: " << ret << std::endl;
|
||||
std::stringstream _sdir;
|
||||
_sdir << "mkdir " << _dir;
|
||||
return (launch_process(_sdir.str().c_str())) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
bool
|
||||
get_bool(const std::string& strbool, bool _default) noexcept
|
||||
{
|
||||
// empty string returns default
|
||||
if(strbool.empty())
|
||||
return _default;
|
||||
|
||||
// check if numeric
|
||||
if(strbool.find_first_not_of("0123456789") == std::string::npos)
|
||||
{
|
||||
if(strbool.length() > 1 || strbool[0] != '0')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert to lowercase
|
||||
auto _val = std::string{ strbool };
|
||||
for(auto& itr : _val)
|
||||
itr = tolower(itr);
|
||||
|
||||
// check for matches to acceptable forms of false
|
||||
for(const auto& itr : { "off", "false", "no", "n", "f" })
|
||||
{
|
||||
if(_val == itr)
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for matches to acceptable forms of true
|
||||
for(const auto& itr : { "on", "true", "yes", "y", "t" })
|
||||
{
|
||||
if(_val == itr)
|
||||
return true;
|
||||
}
|
||||
|
||||
return _default;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
//
|
||||
std::string
|
||||
demangle_backtrace(const char* cstr)
|
||||
{
|
||||
auto _trim = [](std::string& _sub, size_t& _len) {
|
||||
size_t _pos = 0;
|
||||
while(!_sub.empty() && (_pos = _sub.find_first_of(' ')) == 0)
|
||||
{
|
||||
_sub = _sub.erase(_pos, 1);
|
||||
--_len;
|
||||
}
|
||||
while(!_sub.empty() && (_pos = _sub.find_last_of(' ')) == _sub.length() - 1)
|
||||
{
|
||||
_sub = _sub.substr(0, _sub.length() - 1);
|
||||
--_len;
|
||||
}
|
||||
return _sub;
|
||||
};
|
||||
|
||||
auto _save = std::string{ cstr };
|
||||
auto str = demangle(std::string(cstr));
|
||||
if(str.empty())
|
||||
return str;
|
||||
auto beg = str.find("(");
|
||||
if(beg == std::string::npos)
|
||||
{
|
||||
beg = str.find("_Z");
|
||||
if(beg != std::string::npos)
|
||||
beg -= 1;
|
||||
}
|
||||
auto end = str.find("+", beg);
|
||||
if(beg != std::string::npos && end != std::string::npos)
|
||||
{
|
||||
auto len = end - (beg + 1);
|
||||
auto sub = str.substr(beg + 1, len);
|
||||
auto dem = demangle(_trim(sub, len));
|
||||
str = str.replace(beg + 1, len, dem);
|
||||
}
|
||||
else if(beg != std::string::npos)
|
||||
{
|
||||
auto len = str.length() - (beg + 1);
|
||||
auto sub = str.substr(beg + 1, len);
|
||||
auto dem = demangle(_trim(sub, len));
|
||||
str = str.replace(beg + 1, len, dem);
|
||||
}
|
||||
else if(end != std::string::npos)
|
||||
{
|
||||
auto len = end;
|
||||
auto sub = str.substr(beg, len);
|
||||
auto dem = demangle(_trim(sub, len));
|
||||
str = str.replace(beg, len, dem);
|
||||
}
|
||||
|
||||
if(str.empty())
|
||||
{
|
||||
TIMEMORY_TESTING_EXCEPTION(__FUNCTION__ << " resulted in empty string. input: "
|
||||
<< _save);
|
||||
return _save;
|
||||
}
|
||||
|
||||
// cleanup std::_1::basic_<...> types since demangled versions are for diagnostics
|
||||
using pair_t = std::pair<std::string, std::string>;
|
||||
for(auto&& itr : { pair_t{ demangle<std::string>(), "std::string" },
|
||||
pair_t{ demangle<std::istream>(), "std::istream" },
|
||||
pair_t{ demangle<std::ostream>(), "std::ostream" },
|
||||
pair_t{ demangle<std::stringstream>(), "std::stringstream" },
|
||||
pair_t{ demangle<std::istringstream>(), "std::istringstream" },
|
||||
pair_t{ demangle<std::ostringstream>(), "std::ostringstream" } })
|
||||
str = str_transform(str, itr.first, "", [itr](const std::string&) -> std::string {
|
||||
return itr.second;
|
||||
});
|
||||
return str;
|
||||
}
|
||||
//
|
||||
std::string
|
||||
demangle_backtrace(const std::string& str)
|
||||
{
|
||||
return demangle_backtrace(str.c_str());
|
||||
}
|
||||
//
|
||||
std::string
|
||||
demangle_unw_backtrace(const char* cstr)
|
||||
{
|
||||
auto _save = std::string{ cstr };
|
||||
auto _str = tim::demangle(cstr);
|
||||
if(_str.empty())
|
||||
return _str;
|
||||
auto _beg = _str.find("_Z");
|
||||
auto _end = _str.find(" ", _beg);
|
||||
if(_beg != std::string::npos && _end != std::string::npos)
|
||||
{
|
||||
auto _len = _end - _beg;
|
||||
auto _sub = _str.substr(_beg, _len);
|
||||
auto _dem = demangle(_sub);
|
||||
_str = _str.replace(_beg, _len, _dem);
|
||||
}
|
||||
|
||||
if(_str.empty())
|
||||
{
|
||||
TIMEMORY_TESTING_EXCEPTION(__FUNCTION__ << " resulted in empty string. input: "
|
||||
<< _save);
|
||||
return _save;
|
||||
}
|
||||
|
||||
// cleanup std::_1::basic_<...> types since demangled versions are for diagnostics
|
||||
using pair_t = std::pair<std::string, std::string>;
|
||||
for(auto&& itr : { pair_t{ demangle<std::string>(), "std::string" },
|
||||
pair_t{ demangle<std::istream>(), "std::istream" },
|
||||
pair_t{ demangle<std::ostream>(), "std::ostream" },
|
||||
pair_t{ demangle<std::stringstream>(), "std::stringstream" },
|
||||
pair_t{ demangle<std::istringstream>(), "std::istringstream" },
|
||||
pair_t{ demangle<std::ostringstream>(), "std::ostringstream" } })
|
||||
_str =
|
||||
str_transform(_str, itr.first, "", [itr](const std::string&) -> std::string {
|
||||
return itr.second;
|
||||
});
|
||||
|
||||
return _str;
|
||||
}
|
||||
//
|
||||
std::string
|
||||
demangle_unw_backtrace(const std::string& _str)
|
||||
{
|
||||
return demangle_unw_backtrace(_str.c_str());
|
||||
}
|
||||
//
|
||||
#endif // defined(TIMEMORY_UNIX)
|
||||
//
|
||||
std::vector<std::string>
|
||||
read_command_line(pid_t _pid)
|
||||
{
|
||||
std::vector<std::string> _cmdline;
|
||||
#if defined(TIMEMORY_LINUX)
|
||||
std::stringstream fcmdline;
|
||||
fcmdline << "/proc/" << _pid << "/cmdline";
|
||||
std::ifstream ifs(fcmdline.str().c_str());
|
||||
if(ifs)
|
||||
{
|
||||
char cstr;
|
||||
std::string sarg;
|
||||
while(!ifs.eof())
|
||||
{
|
||||
ifs >> cstr;
|
||||
if(!ifs.eof())
|
||||
{
|
||||
if(cstr != '\0')
|
||||
{
|
||||
sarg += cstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cmdline.push_back(sarg);
|
||||
sarg = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
#else
|
||||
consume_parameters(_pid);
|
||||
#endif
|
||||
return _cmdline;
|
||||
}
|
||||
//
|
||||
namespace utility
|
||||
{
|
||||
//
|
||||
path::path(const std::string& _path)
|
||||
: std::string(osrepr(_path))
|
||||
{}
|
||||
|
||||
path::path(char* _path)
|
||||
: std::string(osrepr(std::string(_path)))
|
||||
{}
|
||||
|
||||
path::path(const path& rhs)
|
||||
: std::string(osrepr(rhs))
|
||||
{}
|
||||
|
||||
path::path(const char* _path)
|
||||
: std::string(osrepr(std::string(const_cast<char*>(_path))))
|
||||
{}
|
||||
|
||||
path&
|
||||
path::operator=(const std::string& rhs)
|
||||
{
|
||||
std::string::operator=(osrepr(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
path&
|
||||
path::operator=(const path& rhs)
|
||||
{
|
||||
if(this != &rhs)
|
||||
std::string::operator=(osrepr(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
path&
|
||||
path::insert(size_type __pos, const std::string& __s)
|
||||
{
|
||||
std::string::operator=(osrepr(std::string::insert(__pos, __s)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
path&
|
||||
path::insert(size_type __pos, const path& __s)
|
||||
{
|
||||
std::string::operator=(osrepr(std::string::insert(__pos, __s)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
path::os()
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
return "\\";
|
||||
#elif defined(TIMEMORY_UNIX)
|
||||
return "/";
|
||||
#endif
|
||||
}
|
||||
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
path::inverse()
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
return "/";
|
||||
#elif defined(TIMEMORY_UNIX)
|
||||
return "\\";
|
||||
#endif
|
||||
}
|
||||
|
||||
// OS-dependent representation
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
path::osrepr(std::string _path)
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
while(_path.find('/') != std::string::npos)
|
||||
_path.replace(_path.find('/'), 1, "\\");
|
||||
#elif defined(TIMEMORY_UNIX)
|
||||
while(_path.find("\\\\") != std::string::npos)
|
||||
_path.replace(_path.find("\\\\"), 2, "/");
|
||||
while(_path.find('\\') != std::string::npos)
|
||||
_path.replace(_path.find('\\'), 1, "/");
|
||||
#endif
|
||||
return _path;
|
||||
}
|
||||
//
|
||||
} // namespace utility
|
||||
} // namespace tim
|
||||
//
|
||||
|
||||
#endif // !defined(TIMEMORY_UTILITY_UTILITY_CPP_)
|
||||
@@ -1,882 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// 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 to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
|
||||
/** \file utility/utility.hpp
|
||||
* \headerfile utility/utility.hpp "timemory/utility/utility.hpp"
|
||||
* General utility functions
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "timemory/api.hpp"
|
||||
#include "timemory/macros/compiler.hpp"
|
||||
#include "timemory/macros/language.hpp"
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
#include "timemory/utility/transient_function.hpp"
|
||||
#include "timemory/utility/types.hpp"
|
||||
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
// Without this include on windows launch_process is needed by makedir but is
|
||||
// missing at link time. With this include on linux there is a problem with
|
||||
// delimit not being defined before it is used in popen.hpp. I think including
|
||||
// popen.hpp at the end of this header would be portable and not need the ifdef,
|
||||
// but that would be too weird, so we may have to live with the ifdef. (At
|
||||
// least until makedir is implemented using std::filesystem.)
|
||||
# include "timemory/utility/popen.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(TIMEMORY_USE_LIBUNWIND)
|
||||
# include <libunwind.h>
|
||||
#endif
|
||||
|
||||
// C library
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
// I/O
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iosfwd>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
// general
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <regex>
|
||||
#include <typeindex>
|
||||
#include <utility>
|
||||
// container
|
||||
#include <vector>
|
||||
// threading
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
# include <cxxabi.h>
|
||||
# include <execinfo.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/types.h>
|
||||
#elif defined(TIMEMORY_WINDOWS)
|
||||
# include <direct.h>
|
||||
using pid_t = int;
|
||||
#endif
|
||||
|
||||
#if !defined(DEFAULT_UMASK)
|
||||
# define DEFAULT_UMASK 0777
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
namespace tim
|
||||
{
|
||||
// alias here for common string type
|
||||
// there is also a string_view_t alias in macros/language.hpp which is std::string in
|
||||
// c++14 and std::string_view in c++17 and newer
|
||||
using string_t = std::string;
|
||||
|
||||
/// \typedef std::recursive_mutex mutex_t
|
||||
/// \brief Recursive mutex is used for convenience since the
|
||||
/// performance penalty vs. a regular mutex is not really an issue since there are not
|
||||
/// many locks in general.
|
||||
using mutex_t = std::recursive_mutex;
|
||||
|
||||
/// \typedef std::unique_lock<std::recursive_mutex> auto_lock_t
|
||||
/// \brief Unique lock type around \ref mutex_t
|
||||
using auto_lock_t = std::unique_lock<mutex_t>;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// definition in popen.hpp
|
||||
bool
|
||||
launch_process(const char* cmd, const std::string& extra = "",
|
||||
std::ostream* os = nullptr);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp>
|
||||
inline bool
|
||||
isfinite(const Tp& arg)
|
||||
{
|
||||
#if defined(TIMEMORY_WINDOWS)
|
||||
// Windows seems to be missing std::isfinite
|
||||
return (arg == arg && arg != std::numeric_limits<Tp>::infinity() &&
|
||||
arg != -std::numeric_limits<Tp>::infinity())
|
||||
? true
|
||||
: false;
|
||||
#else
|
||||
return std::isfinite(arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// General functions
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
/// \fn mutex_t& type_mutex(uint64_t)
|
||||
/// \tparam Tp data type for lock
|
||||
/// \tparam ApiT API for lock
|
||||
/// \tparam N max size
|
||||
///
|
||||
/// \brief A simple way to get a mutex for a class or common behavior, e.g.
|
||||
/// `type_mutex<decltype(std::cout)>()` provides a mutex for synchronizing output streams.
|
||||
/// Recommend using in conjunction with auto-lock:
|
||||
/// `tim::auto_lock_t _lk{ type_mutex<Foo>() }`.
|
||||
template <typename Tp, typename ApiT = TIMEMORY_API, size_t N = 4>
|
||||
mutex_t&
|
||||
type_mutex(uint64_t _n = 0)
|
||||
{
|
||||
static std::array<mutex_t, N> _mutexes{};
|
||||
return _mutexes.at(_n % N);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::string
|
||||
demangle(const char* _mangled_name, int* _status = nullptr)
|
||||
{
|
||||
#if defined(TIMEMORY_ENABLE_DEMANGLE)
|
||||
// return the mangled since there is no buffer
|
||||
if(!_mangled_name)
|
||||
return std::string{};
|
||||
|
||||
int _ret = 0;
|
||||
std::string _demangled_name{ _mangled_name };
|
||||
if(!_status)
|
||||
_status = &_ret;
|
||||
|
||||
// PARAMETERS to __cxa_demangle
|
||||
// mangled_name:
|
||||
// A NULL-terminated character string containing the name to be demangled.
|
||||
// buffer:
|
||||
// A region of memory, allocated with malloc, of *length bytes, into which the
|
||||
// demangled name is stored. If output_buffer is not long enough, it is expanded
|
||||
// using realloc. output_buffer may instead be NULL; in that case, the demangled
|
||||
// name is placed in a region of memory allocated with malloc.
|
||||
// _buflen:
|
||||
// If length is non-NULL, the length of the buffer containing the demangled name
|
||||
// is placed in *length.
|
||||
// status:
|
||||
// *status is set to one of the following values
|
||||
char* _demang = abi::__cxa_demangle(_mangled_name, nullptr, nullptr, _status);
|
||||
switch(*_status)
|
||||
{
|
||||
// 0 : The demangling operation succeeded.
|
||||
// -1 : A memory allocation failiure occurred.
|
||||
// -2 : mangled_name is not a valid name under the C++ ABI mangling rules.
|
||||
// -3 : One of the arguments is invalid.
|
||||
case 0:
|
||||
{
|
||||
if(_demang)
|
||||
_demangled_name = std::string{ _demang };
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
{
|
||||
char _msg[1024];
|
||||
::memset(_msg, '\0', 1024 * sizeof(char));
|
||||
::snprintf(_msg, 1024, "memory allocation failure occurred demangling %s",
|
||||
_mangled_name);
|
||||
::perror(_msg);
|
||||
break;
|
||||
}
|
||||
case -2: break;
|
||||
case -3:
|
||||
{
|
||||
char _msg[1024];
|
||||
::memset(_msg, '\0', 1024 * sizeof(char));
|
||||
::snprintf(_msg, 1024, "Invalid argument in: (\"%s\", nullptr, nullptr, %p)",
|
||||
_mangled_name, (void*) _status);
|
||||
::perror(_msg);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
};
|
||||
|
||||
// free allocated buffer
|
||||
::free(_demang);
|
||||
return _demangled_name;
|
||||
#else
|
||||
(void) _status;
|
||||
return _mangled_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline std::string
|
||||
demangle(const std::string& _str, int* _status = nullptr)
|
||||
{
|
||||
return demangle(_str.c_str(), _status);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
try_demangle()
|
||||
{
|
||||
// static because a type demangle will always be the same
|
||||
static auto _val = []() {
|
||||
// wrap the type in type_list and then extract ... from tim::type_list<...>
|
||||
auto _tmp = ::tim::demangle(typeid(type_list<Tp>).name());
|
||||
auto _key = std::string{ "type_list" };
|
||||
auto _idx = _tmp.find(_key);
|
||||
_idx = _tmp.find('<', _idx);
|
||||
_tmp = _tmp.substr(_idx + 1);
|
||||
_idx = _tmp.find_last_of('>');
|
||||
_tmp = _tmp.substr(0, _idx);
|
||||
// strip trailing whitespaces
|
||||
while((_idx = _tmp.find_last_of(' ')) == _tmp.length() - 1)
|
||||
_tmp = _tmp.substr(0, _idx);
|
||||
return _tmp;
|
||||
}();
|
||||
return _val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
demangle()
|
||||
{
|
||||
// static because a type demangle will always be the same
|
||||
static auto _val = demangle(typeid(Tp).name());
|
||||
return _val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template <typename Tp, typename Up = Tp>
|
||||
inline auto
|
||||
typeid_hash(int) -> decltype(demangle<Tp>(), size_t{})
|
||||
{
|
||||
return std::type_index(typeid(Tp)).hash_code();
|
||||
}
|
||||
//
|
||||
template <typename Tp, typename Up = Tp>
|
||||
inline auto
|
||||
typeid_hash(long)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename Tp>
|
||||
inline auto
|
||||
typeid_hash()
|
||||
{
|
||||
return internal::typeid_hash<Tp>(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T>
|
||||
inline T
|
||||
from_string(const std::string& str)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << str;
|
||||
T val{};
|
||||
ss >> val;
|
||||
return val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T>
|
||||
inline T
|
||||
from_string(const char* cstr)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << cstr;
|
||||
T val{};
|
||||
ss >> val;
|
||||
return val;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
dirname(std::string _fname);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_UTILITY_INLINE int
|
||||
makedir(std::string _dir, int umask = DEFAULT_UMASK);
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_UTILITY_INLINE bool
|
||||
get_bool(const std::string& strbool, bool _default = false) noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
#if defined(TIMEMORY_UNIX)
|
||||
//
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
demangle_backtrace(const char* cstr);
|
||||
//
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
demangle_backtrace(const std::string& str);
|
||||
//
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
demangle_unw_backtrace(const char* cstr);
|
||||
//
|
||||
TIMEMORY_UTILITY_INLINE std::string
|
||||
demangle_unw_backtrace(const std::string& str);
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 1>
|
||||
TIMEMORY_NOINLINE auto
|
||||
get_backtrace()
|
||||
{
|
||||
static_assert(Depth > 0, "Error !(Depth > 0)");
|
||||
static_assert(Offset >= 0, "Error !(Offset >= 0)");
|
||||
|
||||
// destination
|
||||
std::array<char[512], Depth> btrace{};
|
||||
for(auto& itr : btrace)
|
||||
itr[0] = '\0';
|
||||
|
||||
// plus one for this stack-frame
|
||||
std::array<void*, Depth + Offset> buffer{};
|
||||
buffer.fill(nullptr);
|
||||
|
||||
// size of returned buffer
|
||||
auto sz = backtrace(buffer.data(), Depth + Offset);
|
||||
// size of relevant data
|
||||
auto n = sz - Offset;
|
||||
|
||||
// skip ahead (Offset + 1) stack frames
|
||||
char** bsym = backtrace_symbols(buffer.data() + Offset, n);
|
||||
|
||||
// report errors
|
||||
if(bsym == nullptr)
|
||||
{
|
||||
perror("backtrace_symbols");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(decltype(n) i = 0; i < n; ++i)
|
||||
{
|
||||
snprintf(btrace[i], sizeof(btrace[i]), "%s", bsym[i]);
|
||||
}
|
||||
}
|
||||
return btrace;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 1>
|
||||
TIMEMORY_NOINLINE auto
|
||||
get_unw_backtrace()
|
||||
{
|
||||
# if defined(TIMEMORY_USE_LIBUNWIND)
|
||||
static_assert(Depth > 0, "Error !(Depth > 0)");
|
||||
static_assert(Offset >= 0, "Error !(Offset >= 0)");
|
||||
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
|
||||
// destination
|
||||
std::array<char[512], Depth> btrace{};
|
||||
for(auto& itr : btrace)
|
||||
itr[0] = '\0';
|
||||
|
||||
// Initialize cursor to current frame for local unwinding.
|
||||
unw_getcontext(&context);
|
||||
if(unw_init_local(&cursor, &context) < 0)
|
||||
{
|
||||
return btrace;
|
||||
}
|
||||
|
||||
size_t tot_idx = 0;
|
||||
while(unw_step(&cursor) > 0)
|
||||
{
|
||||
unw_word_t ip; // stack pointer
|
||||
unw_word_t off; // offset
|
||||
auto _idx = ++tot_idx;
|
||||
if(_idx >= Depth + Offset)
|
||||
break;
|
||||
unw_get_reg(&cursor, UNW_REG_IP, &ip);
|
||||
if(ip == 0)
|
||||
break;
|
||||
char name[496];
|
||||
name[0] = '\0';
|
||||
if(unw_get_proc_name(&cursor, name, sizeof(name), &off) == 0)
|
||||
{
|
||||
if(_idx >= Offset)
|
||||
{
|
||||
auto _lidx = _idx - Offset;
|
||||
if(off)
|
||||
snprintf(btrace[_lidx], sizeof(btrace[_lidx]), "%s +0x%lx", name,
|
||||
(long) off);
|
||||
else
|
||||
snprintf(btrace[_lidx], sizeof(btrace[_lidx]), "%s", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
# else
|
||||
std::array<char[512], Depth> btrace{};
|
||||
throw std::runtime_error("[timemory]> libunwind not available");
|
||||
# endif
|
||||
return btrace;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 1, typename Func>
|
||||
TIMEMORY_NOINLINE auto
|
||||
get_backtrace(Func&& func)
|
||||
{
|
||||
static_assert(Depth > 0, "Error !(Depth > 0)");
|
||||
static_assert(Offset >= 0, "Error !(Offset >= 0)");
|
||||
|
||||
using type = std::result_of_t<Func(const char[512])>;
|
||||
// destination
|
||||
std::array<type, Depth> btrace{};
|
||||
|
||||
auto&& _data = ::tim::get_backtrace<Depth, Offset + 1>();
|
||||
auto _n = _data.size();
|
||||
for(decltype(_n) i = 0; i < _n; ++i)
|
||||
btrace[i] = func(_data[i]);
|
||||
return btrace;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 1, typename Func>
|
||||
TIMEMORY_NOINLINE auto
|
||||
get_unw_backtrace(Func&& func)
|
||||
{
|
||||
static_assert(Depth > 0, "Error !(Depth > 0)");
|
||||
static_assert(Offset >= 0, "Error !(Offset >= 0)");
|
||||
|
||||
using type = std::result_of_t<Func(const char[512])>;
|
||||
// destination
|
||||
std::array<type, Depth> btrace{};
|
||||
|
||||
auto&& _data = ::tim::get_unw_backtrace<Depth, Offset + 1>();
|
||||
auto _n = _data.size();
|
||||
for(decltype(_n) i = 0; i < _n; ++i)
|
||||
btrace[i] = func(_data[i]);
|
||||
return btrace;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 1>
|
||||
TIMEMORY_NOINLINE auto
|
||||
get_demangled_backtrace()
|
||||
{
|
||||
auto demangle_bt = [](const char cstr[512]) { return demangle_backtrace(cstr); };
|
||||
return get_backtrace<Depth, Offset + 1>(demangle_bt);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 1>
|
||||
TIMEMORY_NOINLINE auto
|
||||
get_demangled_unw_backtrace()
|
||||
{
|
||||
auto demangle_bt = [](const char cstr[512]) { return demangle_unw_backtrace(cstr); };
|
||||
return get_unw_backtrace<Depth, Offset + 1>(demangle_bt);
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 2>
|
||||
TIMEMORY_NOINLINE std::ostream&
|
||||
print_backtrace(std::ostream& os = std::cerr, std::string _prefix = "",
|
||||
const std::string& _info = "", const std::string& _indent = " ")
|
||||
{
|
||||
os << _indent.substr(0, _indent.length() / 2) << "Backtrace";
|
||||
if(!_info.empty())
|
||||
os << " " << _info;
|
||||
os << ":\n" << std::flush;
|
||||
auto bt = tim::get_backtrace<Depth, Offset>();
|
||||
if(!_prefix.empty() && _prefix.find_last_of(" \t") != _prefix.length() - 1)
|
||||
_prefix += " ";
|
||||
for(const auto& itr : bt)
|
||||
{
|
||||
if(strlen(itr) > 0)
|
||||
os << _indent << _prefix << itr << "\n";
|
||||
}
|
||||
os << std::flush;
|
||||
return os;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 2>
|
||||
TIMEMORY_NOINLINE std::ostream&
|
||||
print_demangled_backtrace(std::ostream& os = std::cerr, std::string _prefix = "",
|
||||
const std::string& _info = "",
|
||||
const std::string& _indent = " ")
|
||||
{
|
||||
os << _indent.substr(0, _indent.length() / 2) << "Backtrace";
|
||||
if(!_info.empty())
|
||||
os << " " << _info;
|
||||
os << ":\n" << std::flush;
|
||||
auto bt = tim::get_demangled_backtrace<Depth, Offset>();
|
||||
if(!_prefix.empty() && _prefix.find_last_of(" \t") != _prefix.length() - 1)
|
||||
_prefix += " ";
|
||||
for(const auto& itr : bt)
|
||||
{
|
||||
if(itr.length() > 0)
|
||||
os << _indent << _prefix << itr << "\n";
|
||||
}
|
||||
os << std::flush;
|
||||
return os;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 2>
|
||||
TIMEMORY_NOINLINE std::ostream&
|
||||
print_unw_backtrace(std::ostream& os = std::cerr, std::string _prefix = "",
|
||||
const std::string& _info = "", const std::string& _indent = " ")
|
||||
{
|
||||
os << _indent.substr(0, _indent.length() / 2) << "Backtrace";
|
||||
if(!_info.empty())
|
||||
os << " " << _info;
|
||||
os << ":\n" << std::flush;
|
||||
auto bt = tim::get_unw_backtrace<Depth, Offset>();
|
||||
if(!_prefix.empty() && _prefix.find_last_of(" \t") != _prefix.length() - 1)
|
||||
_prefix += " ";
|
||||
for(const auto& itr : bt)
|
||||
{
|
||||
if(strlen(itr) > 0)
|
||||
os << _indent << _prefix << itr << "\n";
|
||||
}
|
||||
os << std::flush;
|
||||
return os;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 3>
|
||||
TIMEMORY_NOINLINE std::ostream&
|
||||
print_demangled_unw_backtrace(std::ostream& os = std::cerr, std::string _prefix = "",
|
||||
const std::string& _info = "",
|
||||
const std::string& _indent = " ")
|
||||
{
|
||||
os << _indent.substr(0, _indent.length() / 2) << "Backtrace";
|
||||
if(!_info.empty())
|
||||
os << " " << _info;
|
||||
os << ":\n" << std::flush;
|
||||
auto bt = tim::get_demangled_unw_backtrace<Depth, Offset>();
|
||||
if(!_prefix.empty() && _prefix.find_last_of(" \t") != _prefix.length() - 1)
|
||||
_prefix += " ";
|
||||
for(const auto& itr : bt)
|
||||
{
|
||||
if(itr.length() > 0)
|
||||
os << _indent << _prefix << itr << "\n";
|
||||
}
|
||||
os << std::flush;
|
||||
return os;
|
||||
}
|
||||
//
|
||||
#else
|
||||
//
|
||||
// define these dummy functions since they are used in operation::decode
|
||||
//
|
||||
static inline auto
|
||||
demangle_backtrace(const char* cstr)
|
||||
{
|
||||
return std::string{ cstr };
|
||||
}
|
||||
//
|
||||
static inline auto
|
||||
demangle_backtrace(const std::string& str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 2>
|
||||
static inline std::ostream&
|
||||
print_backtrace(std::ostream& os = std::cerr, std::string = {}, std::string = {},
|
||||
std::string = {})
|
||||
{
|
||||
os << "[timemory]> Backtrace not supported on this platform\n";
|
||||
return os;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 3>
|
||||
static inline std::ostream&
|
||||
print_demangled_backtrace(std::ostream& os = std::cerr, std::string = {},
|
||||
std::string = {}, std::string = {})
|
||||
{
|
||||
os << "[timemory]> Backtrace not supported on this platform\n";
|
||||
return os;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 2>
|
||||
static inline std::ostream&
|
||||
print_unw_backtrace(std::ostream& os = std::cerr, std::string = {}, std::string = {},
|
||||
std::string = {})
|
||||
{
|
||||
os << "[timemory]> libunwind backtrace not supported on this platform\n";
|
||||
return os;
|
||||
}
|
||||
//
|
||||
template <size_t Depth, size_t Offset = 3>
|
||||
static inline std::ostream&
|
||||
print_demangled_unw_backtrace(std::ostream& os = std::cerr, std::string = {},
|
||||
std::string = {}, std::string = {})
|
||||
{
|
||||
os << "[timemory]> libunwind backtrace not supported on this platform\n";
|
||||
return os;
|
||||
}
|
||||
//
|
||||
#endif
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
// delimit a string into a set
|
||||
//
|
||||
template <typename ContainerT = std::vector<std::string>,
|
||||
typename PredicateT = std::function<std::string(const std::string&)>>
|
||||
inline ContainerT
|
||||
delimit(const std::string& line, const std::string& delimiters = "\"',;: ",
|
||||
PredicateT&& predicate = [](const std::string& s) -> std::string { return s; })
|
||||
{
|
||||
ContainerT _result{};
|
||||
size_t _beginp = 0; // position that is the beginning of the new string
|
||||
size_t _delimp = 0; // position of the delimiter in the string
|
||||
while(_beginp < line.length() && _delimp < line.length())
|
||||
{
|
||||
// find the first character (starting at _delimp) that is not a delimiter
|
||||
_beginp = line.find_first_not_of(delimiters, _delimp);
|
||||
// if no a character after or at _end that is not a delimiter is not found
|
||||
// then we are done
|
||||
if(_beginp == std::string::npos)
|
||||
break;
|
||||
// starting at the position of the new string, find the next delimiter
|
||||
_delimp = line.find_first_of(delimiters, _beginp);
|
||||
std::string _tmp{};
|
||||
try
|
||||
{
|
||||
// starting at the position of the new string, get the characters
|
||||
// between this position and the next delimiter
|
||||
_tmp = line.substr(_beginp, _delimp - _beginp);
|
||||
} catch(std::exception& e)
|
||||
{
|
||||
// print the exception but don't fail, unless maybe it should?
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
}
|
||||
// don't add empty strings
|
||||
if(!_tmp.empty())
|
||||
{
|
||||
_result.insert(_result.end(), predicate(_tmp));
|
||||
}
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
//
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/// \brief apply a string transformation to substring inbetween a common delimiter.
|
||||
/// e.g.
|
||||
//
|
||||
template <typename PredicateT = std::function<std::string(const std::string&)>>
|
||||
inline std::string
|
||||
str_transform(const std::string& input, const std::string& _begin,
|
||||
const std::string& _end, PredicateT&& predicate)
|
||||
{
|
||||
size_t _beg_pos = 0; // position that is the beginning of the new string
|
||||
size_t _end_pos = 0; // position of the delimiter in the string
|
||||
std::string _result = input;
|
||||
while(_beg_pos < _result.length() && _end_pos < _result.length())
|
||||
{
|
||||
// find the first sequence of characters after the end-position
|
||||
_beg_pos = _result.find(_begin, _end_pos);
|
||||
|
||||
// if sequence wasn't found, we are done
|
||||
if(_beg_pos == std::string::npos)
|
||||
break;
|
||||
|
||||
// starting after the position of the first delimiter, find the end sequence
|
||||
if(!_end.empty())
|
||||
_end_pos = _result.find(_end, _beg_pos + 1);
|
||||
else
|
||||
_end_pos = _beg_pos + _begin.length();
|
||||
|
||||
// break if not found
|
||||
if(_end_pos == std::string::npos)
|
||||
break;
|
||||
|
||||
// length of the substr being operated on
|
||||
auto _len = _end_pos - _beg_pos;
|
||||
|
||||
// get the substring between the two delimiters (including first delimiter)
|
||||
auto _sub = _result.substr(_beg_pos, _len);
|
||||
|
||||
// apply the transform
|
||||
auto _transformed = predicate(_sub);
|
||||
|
||||
// only replace if necessary
|
||||
if(_sub != _transformed)
|
||||
{
|
||||
_result = _result.replace(_beg_pos, _len, _transformed);
|
||||
// move end to the end of transformed string
|
||||
_end_pos = _beg_pos + _transformed.length();
|
||||
}
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
//
|
||||
TIMEMORY_UTILITY_INLINE std::vector<std::string>
|
||||
read_command_line(pid_t _pid);
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// path
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
namespace utility
|
||||
{
|
||||
class path : public std::string
|
||||
{
|
||||
public:
|
||||
using size_type = std::string::size_type;
|
||||
|
||||
public:
|
||||
TIMEMORY_UTILITY_INLINE path(const std::string& _path);
|
||||
TIMEMORY_UTILITY_INLINE path(char* _path);
|
||||
TIMEMORY_UTILITY_INLINE path(const path& rhs);
|
||||
TIMEMORY_UTILITY_INLINE path(const char* _path);
|
||||
|
||||
TIMEMORY_UTILITY_INLINE path& operator=(const std::string& rhs);
|
||||
TIMEMORY_UTILITY_INLINE path& operator=(const path& rhs);
|
||||
TIMEMORY_UTILITY_INLINE path& insert(size_type __pos, const std::string& __s);
|
||||
TIMEMORY_UTILITY_INLINE path& insert(size_type __pos, const path& __s);
|
||||
|
||||
// OS-dependent representation
|
||||
static std::string osrepr(std::string _path);
|
||||
static std::string os();
|
||||
static std::string inverse();
|
||||
};
|
||||
} // namespace utility
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T>
|
||||
TIMEMORY_INLINE size_t
|
||||
get_hash(T&& obj)
|
||||
{
|
||||
return std::hash<decay_t<T>>()(std::forward<T>(obj));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_INLINE size_t
|
||||
get_hash(const string_view_t& str)
|
||||
{
|
||||
return std::hash<string_view_t>{}(str);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
TIMEMORY_INLINE size_t
|
||||
get_hash(const char* cstr)
|
||||
{
|
||||
return std::hash<string_view_t>{}(cstr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
template <typename T>
|
||||
struct hasher
|
||||
{
|
||||
inline size_t operator()(T&& val) const { return get_hash(std::forward<T>(val)); }
|
||||
inline size_t operator()(const T& val) const { return get_hash(val); }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
/*
|
||||
#if defined(TIMEMORY_UNIX) && \ (defined(TIMEMORY_UTILITY_SOURCE) ||
|
||||
defined(TIMEMORY_USE_UTILITY_EXTERN))
|
||||
//
|
||||
extern template auto
|
||||
get_backtrace<2, 1>();
|
||||
extern template auto
|
||||
get_backtrace<3, 1>();
|
||||
extern template auto
|
||||
get_backtrace<4, 1>();
|
||||
extern template auto
|
||||
get_backtrace<8, 1>();
|
||||
extern template auto
|
||||
get_backtrace<16, 1>();
|
||||
extern template auto
|
||||
get_backtrace<32, 1>();
|
||||
//
|
||||
extern template auto
|
||||
get_demangled_backtrace<3, 2>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<4, 2>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<8, 2>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<16, 2>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<32, 2>();
|
||||
//
|
||||
extern template auto
|
||||
get_backtrace<3, 2>();
|
||||
extern template auto
|
||||
get_backtrace<4, 2>();
|
||||
extern template auto
|
||||
get_backtrace<8, 2>();
|
||||
extern template auto
|
||||
get_backtrace<16, 2>();
|
||||
extern template auto
|
||||
get_backtrace<32, 2>();
|
||||
//
|
||||
extern template auto
|
||||
get_demangled_backtrace<4, 3>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<8, 3>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<16, 3>();
|
||||
extern template auto
|
||||
get_demangled_backtrace<32, 3>();
|
||||
//
|
||||
#endif
|
||||
*/
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
} // namespace tim
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if defined(TIMEMORY_UTILITY_HEADER_MODE)
|
||||
# include "timemory/utility/utility.cpp"
|
||||
#endif
|
||||
@@ -1,349 +0,0 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// 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 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, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
/** \file timemory/variadic/auto_macros.hpp
|
||||
* \headerfile timemory/variadic/auto_macros.hpp "timemory/variadic/macros.hpp"
|
||||
* Generic macros that are intended to be building-blocks for other macros, e.g.
|
||||
* TIMEMORY_MARKER, TIMEMORY_HANDLE, TIMEMORY_CALIPER, etc.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "timemory/compat/macros.h"
|
||||
#include "timemory/general/source_location.hpp"
|
||||
#include "timemory/macros/os.hpp"
|
||||
#include "timemory/mpl/apply.hpp"
|
||||
#include "timemory/utility/macros.hpp"
|
||||
#include "timemory/utility/utility.hpp"
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// CXX variadic macros
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
namespace tim
|
||||
{
|
||||
// e.g. tim::string::join(...)
|
||||
using string = tim::mpl::apply<std::string>;
|
||||
} // namespace tim
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#if !defined(TIMEMORY_MACROS)
|
||||
|
||||
# define TIMEMORY_MACROS
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// HELPER MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# if !defined(TIMEMORY_WINDOWS)
|
||||
# define TIMEMORY_OS_PATH_DELIMITER '/'
|
||||
# else
|
||||
# define TIMEMORY_OS_PATH_DELIMITER '\\'
|
||||
# endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# if defined(__FILE_NAME__)
|
||||
# define _TIM_FILESTR __FILE_NAME__
|
||||
# else
|
||||
# define _TIM_FILESTR \
|
||||
std::string(__FILE__).substr( \
|
||||
std::string(__FILE__).find_last_of(TIMEMORY_OS_PATH_DELIMITER) + 1)
|
||||
# endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define _TIM_FILELINE ::tim::string::join(':', _TIM_FILESTR, _TIM_LINESTR)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_JOIN(delim, ...) ::tim::string::join(delim, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BLANK_LABEL(...) ::tim::string::join("", __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BASIC_LABEL(...) ::tim::string::join("", _TIM_FUNC, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_FULL_LABEL ::tim::string::join('/', _TIM_FUNC, _TIM_FILELINE)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_LABEL(...) TIMEMORY_JOIN("", TIMEMORY_FULL_LABEL, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_AUTO_TYPE(TYPE) ::tim::concepts::auto_type_t<TYPE>
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_COMP_TYPE(TYPE) ::tim::concepts::component_type_t<TYPE>
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// MARKER MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# define TIMEMORY_BLANK_MARKER(TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(blank, __VA_ARGS__); \
|
||||
TIMEMORY_AUTO_TYPE(TYPE) \
|
||||
_TIM_VARIABLE(__LINE__)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BASIC_MARKER(TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(basic, __VA_ARGS__); \
|
||||
TIMEMORY_AUTO_TYPE(TYPE) \
|
||||
_TIM_VARIABLE(__LINE__)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_MARKER(TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(full, __VA_ARGS__); \
|
||||
TIMEMORY_AUTO_TYPE(TYPE) \
|
||||
_TIM_VARIABLE(__LINE__)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// CONDITIONAL MARKER MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# define TIMEMORY_CONDITIONAL_BLANK_MARKER(COND, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(blank, __VA_ARGS__); \
|
||||
std::unique_ptr<TIMEMORY_AUTO_TYPE(TYPE)> _TIM_VARIABLE(__LINE__) = \
|
||||
std::unique_ptr<TIMEMORY_AUTO_TYPE(TYPE)>( \
|
||||
((COND)) \
|
||||
? new TIMEMORY_AUTO_TYPE(TYPE)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__)) \
|
||||
: nullptr)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CONDITIONAL_BASIC_MARKER(COND, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(basic, __VA_ARGS__); \
|
||||
std::unique_ptr<TIMEMORY_AUTO_TYPE(TYPE)> _TIM_VARIABLE(__LINE__) = \
|
||||
std::unique_ptr<TIMEMORY_AUTO_TYPE(TYPE)>( \
|
||||
((COND)) \
|
||||
? new TIMEMORY_AUTO_TYPE(TYPE)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__)) \
|
||||
: nullptr)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CONDITIONAL_MARKER(COND, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(full, __VA_ARGS__); \
|
||||
std::unique_ptr<TIMEMORY_AUTO_TYPE(TYPE)> _TIM_VARIABLE(__LINE__) = \
|
||||
std::unique_ptr<TIMEMORY_AUTO_TYPE(TYPE)>( \
|
||||
((COND)) \
|
||||
? new TIMEMORY_AUTO_TYPE(TYPE)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__)) \
|
||||
: nullptr)
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// POINTER MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# define TIMEMORY_BLANK_POINTER(TYPE, ...) \
|
||||
TIMEMORY_CONDITIONAL_BLANK_MARKER(::tim::settings::enabled(), TYPE, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BASIC_POINTER(TYPE, ...) \
|
||||
TIMEMORY_CONDITIONAL_BASIC_MARKER(::tim::settings::enabled(), TYPE, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_POINTER(TYPE, ...) \
|
||||
TIMEMORY_CONDITIONAL_MARKER(::tim::settings::enabled(), TYPE, __VA_ARGS__)
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// CALIPER MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# define TIMEMORY_BLANK_CALIPER(ID, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(blank, __VA_ARGS__); \
|
||||
TYPE _TIM_VARIABLE(ID)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BASIC_CALIPER(ID, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(basic, __VA_ARGS__); \
|
||||
TYPE _TIM_VARIABLE(ID)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER(ID, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(full, __VA_ARGS__); \
|
||||
TYPE _TIM_VARIABLE(ID)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_STATIC_BLANK_CALIPER(ID, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(blank, __VA_ARGS__); \
|
||||
static TYPE _TIM_VARIABLE(ID)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_STATIC_BASIC_CALIPER(ID, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(basic, __VA_ARGS__); \
|
||||
static TYPE _TIM_VARIABLE(ID)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_STATIC_CALIPER(ID, TYPE, ...) \
|
||||
_TIM_STATIC_SRC_LOCATION(full, __VA_ARGS__); \
|
||||
static TYPE _TIM_VARIABLE(ID)(TIMEMORY_CAPTURE_ARGS(__VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_REFERENCE(ID) std::ref(_TIM_VARIABLE(ID)).get()
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_APPLY(ID, FUNC, ...) _TIM_VARIABLE(ID).FUNC(__VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_TYPE_APPLY(ID, TYPE, FUNC, ...) \
|
||||
_TIM_VARIABLE(ID).type_apply<TYPE>(FUNC, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_APPLY0(ID, FUNC) _TIM_VARIABLE(ID).FUNC()
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_TYPE_APPLY0(ID, TYPE, FUNC) \
|
||||
_TIM_VARIABLE(ID).type_apply<TYPE>(FUNC)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_LAMBDA(ID, LAMBDA, ...) \
|
||||
LAMBDA(_TIM_VARIABLE(ID), __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CALIPER_TYPE_LAMBDA(ID, TYPE, LAMBDA, ...) \
|
||||
LAMBDA(_TIM_VARIABLE(ID).get<TYPE>(), __VA_ARGS__)
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// HANDLE MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# define TIMEMORY_BLANK_HANDLE(TYPE, ...) \
|
||||
TYPE(TIMEMORY_INLINE_SOURCE_LOCATION(blank, __VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BASIC_HANDLE(TYPE, ...) \
|
||||
TYPE(TIMEMORY_INLINE_SOURCE_LOCATION(basic, __VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_HANDLE(TYPE, ...) \
|
||||
TYPE(TIMEMORY_INLINE_SOURCE_LOCATION(full, __VA_ARGS__))
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BLANK_RAW_POINTER(TYPE, ...) \
|
||||
(::tim::settings::enabled()) \
|
||||
? new TYPE(TIMEMORY_INLINE_SOURCE_LOCATION(blank, __VA_ARGS__)) \
|
||||
: nullptr
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_BASIC_RAW_POINTER(TYPE, ...) \
|
||||
(::tim::settings::enabled()) \
|
||||
? new TYPE(TIMEMORY_INLINE_SOURCE_LOCATION(basic, __VA_ARGS__)) \
|
||||
: nullptr
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_RAW_POINTER(TYPE, ...) \
|
||||
(::tim::settings::enabled()) \
|
||||
? new TYPE(TIMEMORY_INLINE_SOURCE_LOCATION(full, __VA_ARGS__)) \
|
||||
: nullptr
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// DEBUG MACROS
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
# if defined(DEBUG)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_DEBUG_BLANK_MARKER(TYPE, ...) \
|
||||
TIMEMORY_BASIC_MARKER(TYPE, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_DEBUG_BASIC_MARKER(TYPE, ...) \
|
||||
TIMEMORY_BASIC_MARKER(TYPE, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_DEBUG_MARKER(TYPE, ...) TIMEMORY_MARKER(TYPE, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# else
|
||||
# define TIMEMORY_DEBUG_BLANK_MARKER(TYPE, ...)
|
||||
# define TIMEMORY_DEBUG_BASIC_MARKER(TYPE, ...)
|
||||
# define TIMEMORY_DEBUG_MARKER(TYPE, ...)
|
||||
# endif
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
# define TIMEMORY_CONFIGURE(TYPE, ...) TYPE::configure(__VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
// deprecated macros
|
||||
# include "timemory/utility/bits/macros.hpp"
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#endif // !defined(TIMEMORY_MACROS)
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -1,26 +1,98 @@
|
||||
|
||||
#include <perfetto.h>
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <perfetto.h>
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "timemory/api.hpp"
|
||||
#include "timemory/backends/process.hpp"
|
||||
#include "timemory/backends/threading.hpp"
|
||||
#include "timemory/components.hpp"
|
||||
#include "timemory/config.hpp"
|
||||
#include "timemory/environment.hpp"
|
||||
#include "timemory/manager.hpp"
|
||||
#include "timemory/mpl/apply.hpp"
|
||||
#include "timemory/operations.hpp"
|
||||
#include "timemory/settings.hpp"
|
||||
#include "timemory/storage.hpp"
|
||||
#include "timemory/variadic.hpp"
|
||||
|
||||
#if !defined(JOIN)
|
||||
# define JOIN(...) tim::mpl::apply<std::string>::join(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
namespace audit = tim::audit;
|
||||
namespace comp = tim::component;
|
||||
namespace quirk = tim::quirk;
|
||||
|
||||
struct fork_gotcha : tim::component::base<fork_gotcha, void>
|
||||
{
|
||||
using gotcha_data_t = tim::component::gotcha_data;
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(fork_gotcha)
|
||||
|
||||
void audit(const gotcha_data_t& _data, audit::incoming);
|
||||
void audit(const gotcha_data_t& _data, audit::outgoing, pid_t _pid);
|
||||
};
|
||||
|
||||
struct fork_gotcha_api : tim::concepts::api
|
||||
{};
|
||||
|
||||
using fork_gotcha_t =
|
||||
tim::component::gotcha<4, tim::component_tuple<fork_gotcha>, fork_gotcha_api>;
|
||||
using fork_bundle_t =
|
||||
tim::lightweight_tuple<comp::wall_clock, comp::peak_rss, comp::cpu_clock,
|
||||
comp::cpu_util, fork_gotcha_t>;
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
PERFETTO_DEFINE_CATEGORIES(
|
||||
perfetto::Category("hosttrace").SetDescription("Function trace"));
|
||||
|
||||
#if defined(CUSTOM_DATA_SOURCE)
|
||||
class CustomDataSource : public perfetto::DataSource<CustomDataSource>
|
||||
{
|
||||
public:
|
||||
void OnSetup(const SetupArgs&) override
|
||||
{
|
||||
// Use this callback to apply any custom configuration to your data source
|
||||
// based on the TraceConfig in SetupArgs.
|
||||
PRINT_HERE("%s", "setup");
|
||||
}
|
||||
|
||||
void OnStart(const StartArgs&) override
|
||||
{
|
||||
// This notification can be used to initialize the GPU driver, enable
|
||||
// counters, etc. StartArgs will contains the DataSourceDescriptor,
|
||||
// which can be extended.
|
||||
PRINT_HERE("%s", "start");
|
||||
}
|
||||
|
||||
void OnStop(const StopArgs&) override
|
||||
{
|
||||
// Undo any initialization done in OnStart.
|
||||
PRINT_HERE("%s", "stop");
|
||||
}
|
||||
|
||||
// Data sources can also have per-instance state.
|
||||
int my_custom_state = 0;
|
||||
};
|
||||
|
||||
PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
|
||||
#endif
|
||||
|
||||
extern "C" void
|
||||
hosttrace_trace_finalize();
|
||||
|
||||
@@ -33,6 +105,25 @@ get_debug()
|
||||
return _v;
|
||||
}
|
||||
|
||||
void
|
||||
setup_fork_gotcha()
|
||||
{
|
||||
CONDITIONAL_PRINT_HERE(get_debug(), "%s", "configuring gotcha wrapper around fork");
|
||||
|
||||
fork_gotcha_t::get_initializer() = []() {
|
||||
TIMEMORY_C_GOTCHA(fork_gotcha_t, 0, fork);
|
||||
};
|
||||
}
|
||||
|
||||
auto&
|
||||
get_fork_gotcha()
|
||||
{
|
||||
static auto _v =
|
||||
(setup_fork_gotcha(), std::make_unique<fork_bundle_t>(
|
||||
"hosttrace", quirk::config<quirk::auto_start>{}));
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto
|
||||
ensure_finalization()
|
||||
{
|
||||
@@ -69,10 +160,16 @@ get_output_filename()
|
||||
auto _tmp = tim::get_env<std::string>(
|
||||
"HOSTTRACE_OUTPUT_FILE",
|
||||
JOIN('/', tim::get_env<std::string>("PWD", ".", false),
|
||||
"hosttrace.perfetto-trace-%p"));
|
||||
auto _pos = _tmp.find("%p");
|
||||
if(_pos != std::string::npos)
|
||||
_tmp.replace(_pos, 2, std::to_string(tim::process::get_id()));
|
||||
"hosttrace.perfetto-trace-%pid%"));
|
||||
auto _replace = [&_tmp](const std::string& _key, auto _val) {
|
||||
auto _pos = _tmp.find(_key);
|
||||
if(_pos != std::string::npos)
|
||||
_tmp.replace(_pos, _key.length(), std::to_string(_val));
|
||||
};
|
||||
_replace("%pid%", tim::process::get_id());
|
||||
_replace("%rank%", tim::mpi::rank());
|
||||
// backwards compatibility
|
||||
_replace("%p", tim::process::get_id());
|
||||
return _tmp;
|
||||
}();
|
||||
return _v;
|
||||
@@ -107,6 +204,15 @@ hosttrace_init_perfetto()
|
||||
if(get_state() != State::PreInit)
|
||||
return false;
|
||||
|
||||
tim::settings::flamegraph_output() = false;
|
||||
tim::settings::file_output() = false;
|
||||
tim::settings::enable_signal_handler() = true;
|
||||
tim::timemory_init({ "hosttrace" });
|
||||
|
||||
auto& _fork_gotcha = get_fork_gotcha();
|
||||
_fork_gotcha->start();
|
||||
assert(_fork_gotcha->get<fork_gotcha_t>()->get_is_running());
|
||||
|
||||
// environment settings
|
||||
auto shmem_size_hint = tim::get_env<size_t>("HOSTTRACE_SHMEM_SIZE_HINT_KB", 40960);
|
||||
auto buffer_size = tim::get_env<size_t>("HOSTTRACE_BUFFER_SIZE_KB", 1024000);
|
||||
@@ -132,10 +238,25 @@ hosttrace_init_perfetto()
|
||||
|
||||
(void) get_output_filename();
|
||||
|
||||
tim::print_env(std::cerr);
|
||||
tim::print_env(std::cerr,
|
||||
[](const std::string& _v) { return _v.find("HOSTTRACE_") == 0; });
|
||||
|
||||
if(!is_system_backend())
|
||||
{
|
||||
#if defined(CUSTOM_DATA_SOURCE)
|
||||
// Add the following:
|
||||
perfetto::DataSourceDescriptor dsd{};
|
||||
dsd.set_name("com.example.custom_data_source");
|
||||
CustomDataSource::Register(dsd);
|
||||
ds_cfg = cfg.add_data_sources()->mutable_config();
|
||||
ds_cfg->set_name("com.example.custom_data_source");
|
||||
CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
|
||||
auto packet = ctx.NewTracePacket();
|
||||
packet->set_timestamp(perfetto::TrackEvent::GetTraceTimeNs());
|
||||
packet->set_for_testing()->set_str("Hello world!");
|
||||
PRINT_HERE("%s", "Trace");
|
||||
});
|
||||
#endif
|
||||
auto& tracing_session = get_trace_session();
|
||||
tracing_session = perfetto::Tracing::NewTrace();
|
||||
tracing_session->Setup(cfg);
|
||||
@@ -148,6 +269,8 @@ hosttrace_init_perfetto()
|
||||
// created this should ensure that finalization is called before perfetto
|
||||
// ends the tracing session
|
||||
static auto _ensure_finalization = ensure_finalization();
|
||||
|
||||
puts("");
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
@@ -161,6 +284,9 @@ extern "C"
|
||||
// return if not active
|
||||
if(get_state() != State::Active && !hosttrace_init_perfetto())
|
||||
return;
|
||||
// TRACE_EVENT_BEGIN(
|
||||
// "hosttrace", perfetto::StaticString(name),
|
||||
// [&](perfetto::EventContext ctx) { PRINT_HERE("executing %s", name); });
|
||||
TRACE_EVENT_BEGIN("hosttrace", perfetto::StaticString(name));
|
||||
}
|
||||
|
||||
@@ -171,6 +297,8 @@ extern "C"
|
||||
// return if not active
|
||||
if(get_state() != State::Active)
|
||||
return;
|
||||
// TRACE_EVENT_END("hosttrace",
|
||||
// [&](perfetto::EventContext ctx) { PRINT_HERE("executing %s", name); });
|
||||
TRACE_EVENT_END("hosttrace");
|
||||
}
|
||||
|
||||
@@ -188,8 +316,16 @@ extern "C"
|
||||
if(get_state() != State::Active)
|
||||
return;
|
||||
|
||||
puts("");
|
||||
get_state() = State::Finalized;
|
||||
|
||||
if(get_fork_gotcha())
|
||||
{
|
||||
get_fork_gotcha()->stop();
|
||||
std::cout << *get_fork_gotcha() << std::endl;
|
||||
get_fork_gotcha().reset();
|
||||
}
|
||||
|
||||
if(!is_system_backend())
|
||||
{
|
||||
// Make sure the last event is closed for this example.
|
||||
@@ -219,6 +355,8 @@ extern "C"
|
||||
output.write(&trace_data[0], trace_data.size());
|
||||
output.close();
|
||||
}
|
||||
|
||||
tim::timemory_finalize();
|
||||
}
|
||||
|
||||
void hosttrace_trace_set_env(const char* env_name, const char* env_val)
|
||||
@@ -230,6 +368,21 @@ extern "C"
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fork_gotcha::audit(const gotcha_data_t& _data, audit::incoming)
|
||||
{
|
||||
PRINT_HERE("%s",
|
||||
"Warning! Calling fork() within an OpenMPI application using libfabric "
|
||||
"may result is segmentation fault");
|
||||
TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE(get_debug(), 16);
|
||||
}
|
||||
|
||||
void
|
||||
fork_gotcha::audit(const gotcha_data_t& _data, audit::outgoing, pid_t _pid)
|
||||
{
|
||||
PRINT_HERE("%s() return PID %i", _data.tool_id.c_str(), (int) _pid);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
// if static objects are destroyed randomly (relatively uncommon behavior)
|
||||
@@ -239,3 +392,8 @@ auto _ensure_finalization = ensure_finalization();
|
||||
} // namespace
|
||||
|
||||
PERFETTO_TRACK_EVENT_STATIC_STORAGE();
|
||||
TIMEMORY_INITIALIZE_STORAGE(fork_gotcha)
|
||||
|
||||
#if defined(CUSTOM_DATA_SOURCE)
|
||||
PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
|
||||
#endif
|
||||
|
||||
مرجع در شماره جدید
Block a user