pax_global_header00006660000000000000000000000064141000030730014476gustar00rootroot0000000000000052 comment=9599f724d4edc3a3d973bac14eeebdc1bc31d327 libpmemobj-cpp-1.13.0/000077500000000000000000000000001410000307300144605ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/.clang-format000066400000000000000000000016351410000307300170400ustar00rootroot00000000000000AccessModifierOffset: -8 AlignOperands: false AllowShortBlocksOnASingleLine: false AllowShortFunctionsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: true AlwaysBreakTemplateDeclarations: true BasedOnStyle: LLVM BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: true AfterNamespace: true AfterObjCDeclaration: false AfterStruct: false AfterUnion: false BeforeCatch: false BeforeElse: false IndentBraces: false BreakBeforeBraces: Custom BreakStringLiterals: false ConstructorInitializerAllOnOneLineOrOnePerLine: true ContinuationIndentWidth: 8 FixNamespaceComments: false IndentCaseLabels: true IndentWidth: 8 PointerAlignment: Right SpaceBeforeParens: ControlStatements SpacesBeforeTrailingComments: 1 SpacesInContainerLiterals: false SpacesInCStyleCastParentheses: false UseTab: Always libpmemobj-cpp-1.13.0/.gitattributes000066400000000000000000000001071410000307300173510ustar00rootroot00000000000000* text=auto eol=lf *.jpg binary *.png binary *.gif binary *.ico binary libpmemobj-cpp-1.13.0/.github/000077500000000000000000000000001410000307300160205ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/.github/ISSUE_TEMPLATE/000077500000000000000000000000001410000307300202035ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000035021410000307300226750ustar00rootroot00000000000000--- name: Bug report about: Did you find a bug in libpmemobj-cpp? Please let us know. labels: "Type: Bug" --- # ISSUE: ## Environment Information - libpmemobj-cpp version(s): - PMDK (libpmemobj) package version(s): - OS(es) version(s): - kernel version(s): - compiler, libraries, packaging and other related tools version(s): and possibly: - TBB version(s): - ndctl version(s): ## Please provide a reproduction of the bug: ## How often bug is revealed: (always, often, rare) ## Actual behavior: ## Expected behavior: ## Details ## Additional information about Priority and Help Requested: Are you willing to submit a pull request with a proposed change? (Yes, No) Requested priority: (Showstopper, High, Medium, Low) libpmemobj-cpp-1.13.0/.github/ISSUE_TEMPLATE/feature.md000066400000000000000000000005101410000307300221540ustar00rootroot00000000000000--- name: Feature about: Request a feature labels: "Type: Feature" --- # FEAT: ## Rationale ## Description ## API Changes ## Implementation details ## Meta libpmemobj-cpp-1.13.0/.github/ISSUE_TEMPLATE/question.md000066400000000000000000000006331410000307300223760ustar00rootroot00000000000000--- name: Question about: Do you have question regarding libpmemobj-cpp? Don't hesitate to ask. labels: "Type: Question" --- # QUESTION: ## Details libpmemobj-cpp-1.13.0/.github/workflows/000077500000000000000000000000001410000307300200555ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/.github/workflows/coverity.yml000066400000000000000000000021001410000307300224350ustar00rootroot00000000000000 name: CPP-coverity # It runs static analysis build - Coverity. It requires special token (set in CI's secret). on: schedule: # run this job at 00:00 UTC everyday - cron: '0 0 * * *' env: REPO: libpmemobj-cpp GITHUB_REPO: pmem/libpmemobj-cpp CONTAINER_REG: ghcr.io/pmem/libpmemobj-cpp HOST_WORKDIR: ${{ github.workspace }} WORKDIR: utils/docker IMG_VER: latest COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }} COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} jobs: linux: name: Linux-coverity runs-on: ubuntu-latest strategy: matrix: CONFIG: ["TYPE=coverity OS=ubuntu OS_VER=20.04"] steps: - name: Clone the git repo uses: actions/checkout@v2 # coverity workflow should just reuse (pull) the most recent, available image - name: Pull the image run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh pull - name: Run the build run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh libpmemobj-cpp-1.13.0/.github/workflows/gha.yml000066400000000000000000000143631410000307300213460ustar00rootroot00000000000000name: CPP # It runs default OSes for each PR, push event or a new tag, # checks basic builds with various compilers and executes all sets of tests. on: push: pull_request: release: types: - created env: REPO: libpmemobj-cpp GITHUB_REPO: pmem/libpmemobj-cpp CONTAINER_REG: ghcr.io/pmem/libpmemobj-cpp HOST_WORKDIR: ${{ github.workspace }} TEST_TIMEOUT: 600 IMG_VER: latest jobs: linux: name: Linux runs-on: ubuntu-latest env: # use org's Private Access Token to log in to GitHub Container Registry CONTAINER_REG_USER: ${{ secrets.GH_CR_USER }} CONTAINER_REG_PASS: ${{ secrets.GH_CR_PAT }} FORCE_IMAGE_ACTION: ${{ secrets.FORCE_IMAGE_ACTION }} WORKDIR: utils/docker strategy: matrix: CONFIG: ["TYPE=debug OS=fedora OS_VER=32 PUSH_IMAGE=1", "TYPE=debug OS=ubuntu OS_VER=20.04 PUSH_IMAGE=1 CHECK_CPP_STYLE=1", "TYPE=debug OS=ubuntu OS_VER=20.04 COVERAGE=1", "TYPE=release OS=fedora OS_VER=32", "TYPE=release OS=ubuntu OS_VER=20.04", "TYPE=valgrind OS=ubuntu OS_VER=20.04", "TYPE=memcheck_drd OS=ubuntu OS_VER=20.04", "TYPE=package OS=fedora OS_VER=32", "TYPE=package OS=ubuntu OS_VER=20.04"] steps: - name: Get release version if: github.event_name == 'release' id: get_release_version run: echo ::set-output name=VERSION::$(echo ${{ github.event.release.tag_name }} | grep -E "^[0-9]+.[0-9]+(-rc[0-9]+)?$" | cut -f 1,2 -d . | cut -f 1 -d -) - name: Set image version and force image action for release if: github.event_name == 'release' && steps.get_release_version.outputs.VERSION != '' run: | echo "IMG_VER=${{ steps.get_release_version.outputs.VERSION }}" >> $GITHUB_ENV echo "FORCE_IMAGE_ACTION=rebuild" >> $GITHUB_ENV - name: Set image version and force image action for stable branch if: startsWith(github.ref, 'refs/heads/stable-') run: | echo "IMG_VER=$(echo ${GITHUB_REF#refs/heads/} | cut -d - -f 2)" >> $GITHUB_ENV echo "FORCE_IMAGE_ACTION=rebuild" >> $GITHUB_ENV - name: Clone the git repo uses: actions/checkout@v2 with: fetch-depth: 0 # "pull" or "rebuild" can be passed to a secret FORCE_IMAGE_ACTION to override default action - name: Pull the image or rebuild and push it run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh $FORCE_IMAGE_ACTION - name: Run the build run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh doc: name: build and publish docs runs-on: ubuntu-latest needs: linux env: DOC_UPDATE_GITHUB_TOKEN: ${{ secrets.DOC_UPDATE_GITHUB_TOKEN }} DOC_UPDATE_BOT_NAME: ${{ secrets.DOC_UPDATE_BOT_NAME }} DOC_REPO_OWNER: ${{ secrets.DOC_REPO_OWNER }} WORKDIR: utils/docker if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/stable-') strategy: matrix: CONFIG: ["TYPE=doc OS=fedora OS_VER=32"] steps: - name: Clone the git repo uses: actions/checkout@v2 with: fetch-depth: 0 - name: Pull the image run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh pull - name: Run the build run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh windows: name: Windows runs-on: windows-latest env: platform: x64 VCPKG_DEFAULT_TRIPLET: x64-windows GENERATOR: "Visual Studio 16 2019" ARCH: "x64" PMDK_VERSION: "1.9" CMAKE_TOOLCHAIN_FILE: "C:\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" CMAKE_INSTALL_PREFIX: "C:\\install\\libpmemobj-cpp" MSBUILD: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin" strategy: matrix: BUILD_TYPE: [Debug, Release] CXX_STANDARD: [14] include: - BUILD_TYPE: RelWithDebInfo CXX_STANDARD: 17 steps: - name: Update PATH run: echo "${env:MSBUILD}" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Cache vcpkg packages uses: actions/cache@v1 id: cache-vcpkg-packages with: path: C:/vcpkg/packages key: vcpkg-packages-45e5a67 - name: Cache vcpkg installed uses: actions/cache@v1 id: cache-vcpkg-installed with: path: C:/vcpkg/installed key: vcpkg-installed-45e5a67 - name: Clone the git repo uses: actions/checkout@v2 with: fetch-depth: 0 - name: Install PMDK run: | vcpkg install pmdk:x64-windows vcpkg install sfml:x64-windows vcpkg install tbb:x64-windows vcpkg update vcpkg upgrade pmdk:x64-windows --no-dry-run - name: vcpkg integrate install run: vcpkg integrate install - name: Configure run: cmake . -Bbuild -G "${env:GENERATOR}" -A "${env:ARCH}" -DCMAKE_BUILD_TYPE="${{ matrix.BUILD_TYPE }}" -DCMAKE_TOOLCHAIN_FILE="${env:CMAKE_TOOLCHAIN_FILE}" -DCMAKE_INSTALL_PREFIX="${env:CMAKE_INSTALL_PREFIX}" -DTESTS_USE_FORCED_PMEM=ON -DTESTS_USE_VALGRIND=OFF -DTESTS_TBB=ON -DDEVELOPER_MODE=ON -DCXX_STANDARD="${{ matrix.CXX_STANDARD }}" - name: Build run: msbuild build/ALL_BUILD.vcxproj /property:Configuration=${{ matrix.BUILD_TYPE }} /verbosity:minimal /m - name: Tests working-directory: build run: ctest -C ${{ matrix.BUILD_TYPE }} --output-on-failure --timeout "${env:TEST_TIMEOUT}" - name: Install working-directory: build run: msbuild INSTALL.vcxproj /verbosity:minimal /m - name: Examples working-directory: examples/map_cli run: | cmake . -G "${env:GENERATOR}" -A "${env:ARCH}" -DCMAKE_TOOLCHAIN_FILE="${env:CMAKE_TOOLCHAIN_FILE}" -DCMAKE_PREFIX_PATH="${env:CMAKE_INSTALL_PREFIX}" msbuild ALL_BUILD.vcxproj /verbosity:minimal /m libpmemobj-cpp-1.13.0/.github/workflows/nightly.yml000066400000000000000000000033131410000307300222560ustar00rootroot00000000000000 name: CPP-nightly # It runs non-deafult OSes, listed below with basic set of compilers and tests. on: schedule: # run this job at 01:00 UTC everyday - cron: '0 1 * * *' env: REPO: libpmemobj-cpp GITHUB_REPO: pmem/libpmemobj-cpp CONTAINER_REG: ghcr.io/pmem/libpmemobj-cpp HOST_WORKDIR: ${{ github.workspace }} WORKDIR: utils/docker TEST_TIMEOUT: 900 IMG_VER: latest TYPE: debug PUSH_IMAGE: 1 # use org's Private Access Token to log in to GitHub Container Registry CONTAINER_REG_USER: ${{ secrets.GH_CR_USER }} CONTAINER_REG_PASS: ${{ secrets.GH_CR_PAT }} jobs: linux: name: Linux-nightly runs-on: ubuntu-latest strategy: fail-fast: false matrix: CONFIG: ["OS=centos OS_VER=8", "OS=archlinux-base OS_VER=latest", "OS=debian OS_VER=testing", "OS=debian OS_VER=unstable", "OS=debian OS_VER=latest", "OS=fedora OS_VER=33", "OS=fedora OS_VER=34", "OS=fedora OS_VER=rawhide TESTS_PMREORDER=0", "OS=opensuse-leap OS_VER=latest", "OS=opensuse-tumbleweed OS_VER=latest", "OS=ubuntu OS_VER=18.04", "OS=ubuntu OS_VER=21.04", "OS=ubuntu OS_VER=devel"] steps: - name: Clone the git repo uses: actions/checkout@v2 # It rebuilds images every time and pushes them to the container registry - name: Rebuild and push the image run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh rebuild - name: Run the build run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh libpmemobj-cpp-1.13.0/.github/workflows/weekly.yml000066400000000000000000000031641410000307300221040ustar00rootroot00000000000000 name: CPP-weekly # It runs non-day-to-day checks; "unusual" jobs required to be checked only once in a while. on: schedule: # run this job at 01:00 UTC every Saturday - cron: '0 1 * * 6' env: REPO: libpmemobj-cpp GITHUB_REPO: pmem/libpmemobj-cpp CONTAINER_REG: ghcr.io/pmem/libpmemobj-cpp HOST_WORKDIR: ${{ github.workspace }} WORKDIR: utils/docker TEST_TIMEOUT: 900 IMG_VER: latest PUSH_IMAGE: 0 jobs: linux: name: Linux-weekly runs-on: ubuntu-latest strategy: fail-fast: false matrix: CONFIG: ["TYPE=debug OS=ubuntu OS_VER=20.04 TESTS_ASAN=1 TESTS_PMREORDER=0", "TYPE=debug OS=ubuntu OS_VER=20.04 TESTS_UBSAN=1 TESTS_PMREORDER=0", "TYPE=debug OS=fedora OS_VER=rawhide TESTS_ASAN=1 TESTS_PMREORDER=0", "TYPE=debug OS=fedora OS_VER=rawhide TESTS_UBSAN=1 TESTS_PMREORDER=0", "TYPE=valgrind OS=fedora OS_VER=rawhide TESTS_PMREORDER=0", "TYPE=memcheck_drd OS=fedora OS_VER=rawhide TESTS_PMREORDER=0", "TYPE=package OS=fedora OS_VER=34", "TYPE=package OS=fedora OS_VER=rawhide TESTS_PMREORDER=0", "TYPE=package OS=ubuntu OS_VER=devel"] steps: - name: Clone the git repo uses: actions/checkout@v2 # It rebuilds images every time (push is not neccessary; they are pushed in other workflows) - name: Rebuild the image run: cd $WORKDIR && ${{ matrix.CONFIG }} ./pull-or-rebuild-image.sh rebuild - name: Run the build run: cd $WORKDIR && ${{ matrix.CONFIG }} ./build.sh libpmemobj-cpp-1.13.0/.gitignore000066400000000000000000000001371410000307300164510ustar00rootroot00000000000000.* !.clang-format !.gitattributes !.gitignore !.github/ !.mailmap !.version build/ *~ *.swp ~* libpmemobj-cpp-1.13.0/.mailmap000066400000000000000000000002151410000307300160770ustar00rootroot00000000000000Igor Chorążewicz Michał Biesek Krzysztof Kajrewicz libpmemobj-cpp-1.13.0/.version000066400000000000000000000000071410000307300161430ustar00rootroot000000000000001.13.0 libpmemobj-cpp-1.13.0/CMakeLists.txt000066400000000000000000000314621410000307300172260ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause # Copyright 2018-2021, Intel Corporation cmake_minimum_required(VERSION 3.3) project(libpmemobj-cpp C CXX) set(LIBPMEMOBJCPP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # ----------------------------------------------------------------- # ## Set required and useful variables # ----------------------------------------------------------------- # set(VERSION_MAJOR 1) set(VERSION_MINOR 13) set(VERSION_PATCH 0) #set(VERSION_PRERELEASE rc2) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}) if(VERSION_PATCH GREATER 0) set(VERSION ${VERSION}.${VERSION_PATCH}) endif() if(VERSION_PRERELEASE) set(VERSION ${VERSION}-${VERSION_PRERELEASE}) endif() set(CXX_STANDARD 14 CACHE STRING "C++ language standard") set(CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD ${CXX_STANDARD}) # Specify and print the build type set(DEFAULT_BUILD_TYPE "RelWithDebInfo") set(predefined_build_types Debug Release RelWithDebInfo MinSizeRel) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE ${DEFAULT_BUILD_TYPE} CACHE STRING "choose the type of build (${predefined_build_types})" FORCE) message(STATUS "CMAKE_BUILD_TYPE not set, setting the default one: ${CMAKE_BUILD_TYPE}") else() message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") if(NOT CMAKE_BUILD_TYPE IN_LIST predefined_build_types) message(WARNING "Unusual build type was set, please make sure it's proper one. " "By default supported are only following: ${predefined_build_types}.") endif() endif() include(${LIBPMEMOBJCPP_ROOT_DIR}/cmake/functions.cmake) # set SRCVERSION, it's more accurate and "current" than VERSION set_source_ver(SRCVERSION) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${LIBPMEMOBJCPP_ROOT_DIR}/cmake) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) set(LIBPMEMOBJ_REQUIRED_VERSION 1.9) set(LIBPMEM_REQUIRED_VERSION 1.7) # Only pmreorder in ver. >= 1.9 guarantees reliable output set(PMREORDER_REQUIRED_VERSION 1.9) set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test CACHE STRING "working directory for tests") message(STATUS "TEST_DIR set to: \"${TEST_DIR}\"") # Do not treat include directories from the interfaces # of consumed Imported Targets as SYSTEM by default. set(CMAKE_NO_SYSTEM_FROM_IMPORTED 1) # ----------------------------------------------------------------- # ## CMake build options # ----------------------------------------------------------------- # option(BUILD_EXAMPLES "build examples" ON) option(BUILD_TESTS "build tests" ON) option(BUILD_DOC "build documentation" ON) option(BUILD_BENCHMARKS "build benchmarks" ON) option(COVERAGE "enable collecting of coverage data" OFF) option(DEVELOPER_MODE "enable developer checks" OFF) option(CHECK_CPP_STYLE "check code style of C++ sources" OFF) option(TRACE_TESTS "more verbose test outputs" OFF) option(USE_ASAN "enable AddressSanitizer (debugging)" OFF) option(USE_UBSAN "enable UndefinedBehaviorSanitizer (debugging)" OFF) option(USE_CCACHE "use ccache if it is available in the system" ON) option(TESTS_USE_FORCED_PMEM "run tests with PMEM_IS_PMEM_FORCE=1 - it speeds up tests execution on emulated pmem" OFF) option(TESTS_USE_VALGRIND "enable tests with valgrind (fail build if Valgrind not found)" ON) option(TESTS_PMREORDER "enable tests with pmreorder (if pmreorder found; it requires PMDK ver. >= 1.9)" OFF) option(TESTS_CONCURRENT_HASH_MAP_DRD_HELGRIND "enable concurrent_hash_map tests with drd and helgrind (can only be run on PMEM)" OFF) option(TESTS_CONCURRENT_GDB "enable concurrent gdb tests - require 'set scheduler-locking on' support (OS dependent)" OFF) option(TESTS_LONG "enable long running tests" OFF) option(TESTS_TBB "enable tests which require TBB" OFF) option(TESTS_COMPATIBILITY "enable compatibility tests (requires internet connection)" OFF) option(TEST_ARRAY "enable testing of pmem::obj::array" ON) option(TEST_VECTOR "enable testing of pmem::obj::vector" ON) option(TEST_STRING "enable testing of pmem::obj::string (depends on TEST_VECTOR)" ON) option(TEST_CONCURRENT_HASHMAP "enable testing of pmem::obj::concurrent_hash_map (depends on TEST_STRING)" ON) option(TEST_SEGMENT_VECTOR_ARRAY_EXPSIZE "enable testing of pmem::obj::segment_vector with array as segment_vector_type and exponential_size_policy" ON) option(TEST_SEGMENT_VECTOR_VECTOR_EXPSIZE "enable testing of pmem::obj::segment_vector with vector as segment_vector_type and exponential_size_policy" ON) option(TEST_SEGMENT_VECTOR_VECTOR_FIXEDSIZE "enable testing of pmem::obj::segment_vector with vector as segment_vector_type and fixed_size_policy" ON) option(TEST_ENUMERABLE_THREAD_SPECIFIC "enable testing of pmem::obj::enumerable_thread_specific" ON) option(TEST_CONCURRENT_MAP "enable testing of pmem::obj::experimental::concurrent_map (depends on TEST_STRING)" ON) option(TEST_SELF_RELATIVE_POINTER "enable testing of pmem::obj::experimental::self_relative_ptr" ON) option(TEST_RADIX_TREE "enable testing of pmem::obj::experimental::radix_tree" ON) option(TEST_MPSC_QUEUE "enable testing of pmem::obj::experimental::mpsc_queue" ON) # ----------------------------------------------------------------- # ## Setup environment, find packages, set compiler's flags, ## add additional custom targets, ... # ----------------------------------------------------------------- # include(FindPerl) include(FindThreads) include(CMakeDependentOption) include(CMakePackageConfigHelpers) include(CheckCXXSourceCompiles) include(CheckCXXCompilerFlag) include(GNUInstallDirs) # Configure the ccache as compiler launcher find_program(CCACHE_FOUND ccache) if(USE_CCACHE AND CCACHE_FOUND) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) endif() if(WIN32) # Required for MSVC to correctly define __cplusplus add_flag("/Zc:__cplusplus") endif() if(NOT WIN32) find_package(PkgConfig QUIET) endif() # Finds valgrind and checks for pmemcheck's availability if(PKG_CONFIG_FOUND) pkg_check_modules(VALGRIND QUIET valgrind) else() find_package(VALGRIND QUIET) endif() if(VALGRIND_FOUND) message(STATUS "Found Valgrind in '${VALGRIND_LIBRARY_DIRS}' (version: ${VALGRIND_VERSION})") add_flag(-DLIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED=1) add_flag(-DLIBPMEMOBJ_CPP_VG_DRD_ENABLED=1) add_flag(-DLIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED=1) include_directories(${VALGRIND_INCLUDE_DIRS}) find_pmemcheck() if(VALGRIND_PMEMCHECK_FOUND) add_flag(-DLIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED=1) endif() elseif(NOT VALGRIND_FOUND AND TESTS_USE_VALGRIND) message(FATAL_ERROR "Valgrind not found, but flag TESTS_USE_VALGRIND was set.") elseif(NOT VALGRIND_FOUND) message(WARNING "Valgrind not found. Valgrind tests will not be performed.") endif() if(BUILD_TESTS OR BUILD_EXAMPLES OR BUILD_BENCHMARKS) # Find libpmem and libpmemobj (PMDK libraries) if(PKG_CONFIG_FOUND) pkg_check_modules(LIBPMEMOBJ REQUIRED libpmemobj>=${LIBPMEMOBJ_REQUIRED_VERSION}) pkg_check_modules(LIBPMEM REQUIRED libpmem>=${LIBPMEM_REQUIRED_VERSION}) else() find_package(LIBPMEMOBJ REQUIRED ${LIBPMEMOBJ_REQUIRED_VERSION}) find_package(LIBPMEM REQUIRED ${LIBPMEM_REQUIRED_VERSION}) endif() # Some tests and examples require clang >= 8.0, because of the bug # (https://bugs.llvm.org/show_bug.cgi?id=28280), which is fixed in clang v8.0. if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang" AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.0") set(CLANG_DESTRUCTOR_REFERENCE_BUG_PRESENT 1) endif() endif() endif() add_custom_target(checkers ALL) add_custom_target(cppstyle) add_custom_target(cppformat) add_custom_target(check-whitespace) add_custom_target(check-license COMMAND ${LIBPMEMOBJCPP_ROOT_DIR}/utils/check_license/check-headers.sh ${LIBPMEMOBJCPP_ROOT_DIR} BSD-3-Clause) if(CHECK_CPP_STYLE) find_program(CLANG_FORMAT NAMES clang-format clang-format-9 clang-format-9.0) set(CLANG_FORMAT_REQUIRED "9.0") if(CLANG_FORMAT) get_program_version_major_minor(${CLANG_FORMAT} CLANG_FORMAT_VERSION) message(STATUS "Found clang-format: ${CLANG_FORMAT} (version: ${CLANG_FORMAT_VERSION})") if(NOT (CLANG_FORMAT_VERSION VERSION_EQUAL CLANG_FORMAT_REQUIRED)) message(FATAL_ERROR "required clang-format version is ${CLANG_FORMAT_REQUIRED}") endif() else() message(FATAL_ERROR "CHECK_CPP_STYLE=ON, but clang-format not found (required version: ${CLANG_FORMAT_REQUIRED})") endif() add_dependencies(checkers cppstyle) endif() if(DEVELOPER_MODE) # treat compiler warnings as errors if(WIN32) add_flag(-WX) else() add_flag(-Werror) # check for required programs for whitespace and license checks and add dependencies to ALL if(NOT PERL_FOUND) message(FATAL_ERROR "Perl not found") endif() if(PERL_VERSION_STRING VERSION_LESS 5.16) message(FATAL_ERROR "Too old Perl (<5.16)") endif() execute_process(COMMAND ${PERL_EXECUTABLE} -MText::Diff -e "" ERROR_QUIET RESULT_VARIABLE PERL_TEXT_DIFF_STATUS) if(PERL_TEXT_DIFF_STATUS) message(FATAL_ERROR "Text::Diff Perl module not found (install libtext-diff-perl or perl-Text-Diff)") endif() add_dependencies(checkers check-whitespace) add_dependencies(checkers check-license) endif() endif() add_cppstyle(include ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/*.hpp) add_cppstyle(include-container ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/container/*.hpp) add_cppstyle(include-container-detail ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/container/detail/*.hpp) add_cppstyle(include-detail ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/detail/*.hpp) add_cppstyle(include-experimental ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/experimental/*.hpp) add_check_whitespace(main ${LIBPMEMOBJCPP_ROOT_DIR}/utils/check_license/*.sh ${LIBPMEMOBJCPP_ROOT_DIR}/*.md) add_check_whitespace(include ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/*.hpp) add_check_whitespace(include-container ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/container/*.hpp) add_check_whitespace(include-container-detail ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/container/detail/*.hpp) add_check_whitespace(include-detail ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/detail/*.hpp) add_check_whitespace(include-experimental ${CMAKE_CURRENT_SOURCE_DIR}/include/libpmemobj++/experimental/*.hpp) add_check_whitespace(cmake-main ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) add_check_whitespace(cmake-helpers ${CMAKE_CURRENT_SOURCE_DIR}/cmake/*.cmake) # ----------------------------------------------------------------- # ## Configure make install/uninstall and packages # ----------------------------------------------------------------- # configure_file(${LIBPMEMOBJCPP_ROOT_DIR}/cmake/version.hpp.in ${CMAKE_CURRENT_BINARY_DIR}/version.hpp @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/version.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpmemobj++) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} FILES_MATCHING PATTERN "*.hpp") install(DIRECTORY examples/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/examples FILES_MATCHING PATTERN "*.*pp") configure_file(${LIBPMEMOBJCPP_ROOT_DIR}/cmake/libpmemobj++.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libpmemobj++.pc @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpmemobj++.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) configure_file( "${LIBPMEMOBJCPP_ROOT_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) configure_package_config_file(${LIBPMEMOBJCPP_ROOT_DIR}/cmake/libpmemobj++-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libpmemobj++-config.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpmemobj++/cmake PATH_VARS CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR) write_basic_package_version_file(libpmemobj++-config-version.cmake VERSION ${VERSION} COMPATIBILITY AnyNewerVersion) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpmemobj++-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/libpmemobj++-config-version.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpmemobj++/cmake) # set up project's include dir (our source 'include' dir) include_directories(include) # Run checks for known issues, it's required to enable/disable some tests and examples. # It has to be executed (included) here, when environment is fully set up, # all packages are found and all paths/variables are set. include(${LIBPMEMOBJCPP_ROOT_DIR}/cmake/check_compiling_issues.cmake) # ----------------------------------------------------------------- # ## Add/include sub-directories if build options enabled them # ----------------------------------------------------------------- # if(BUILD_TESTS) enable_testing() add_subdirectory(tests) endif() if(BUILD_DOC) add_subdirectory(doc) endif() if(BUILD_BENCHMARKS) add_subdirectory(benchmarks) endif() if(BUILD_EXAMPLES AND NO_GCC_VARIADIC_TEMPLATE_BUG) add_subdirectory(examples) elseif(BUILD_EXAMPLES) message(WARNING "Skipping building of examples because of gcc variadic template bug") endif() if(NOT "${CPACK_GENERATOR}" STREQUAL "") include(${LIBPMEMOBJCPP_ROOT_DIR}/cmake/packages.cmake) endif() libpmemobj-cpp-1.13.0/CONTRIBUTING.md000066400000000000000000000143431410000307300167160ustar00rootroot00000000000000# Contributing to libpmemobj-cpp - [Opening New Issues](#opening-new-issues) - [Code Style](#code-style) - [Submitting Pull Requests](#submitting-pull-requests) - [Implementing persistent containers](#implementing-persistent-containers) - [Configuring GitHub fork](#configuring-github-fork) # Opening New Issues Please log bugs or suggestions as [GitHub issues](https://github.com/pmem/libpmemobj-cpp/issues). Details such as OS and PMDK version are always appreciated. # Code Style * See `.clang-format` file in the repository for details * Indent with tabs (width: 8) * Max 90 chars per line * Space before '*' and '&' (rather than after) If you want to check and format your source code properly you can use CMake's `DEVELOPER_MODE` and `CHECK_CPP_STYLE` options. When enabled additional checks are switched on (cppstyle, whitespace and license). ```sh cmake .. -DDEVELOPER_MODE=ON -DCHECK_CPP_STYLE=ON ``` If you just want to format your code you can make adequate target: ```sh make cppformat ``` **NOTE**: We're using specific clang-format - version exactly **9.0** is required. # Submitting Pull Requests We take outside code contributions to `libpmemobj-cpp` through GitHub pull requests. If you add a new feature or fix a critical bug please append appropriate entry to ChangeLog under newest release. **NOTE: If you do decide to implement code changes and contribute them, please make sure you agree your contribution can be made available under the [BSD-style License used for libpmemobj-cpp](LICENSE).** **NOTE: Submitting your changes also means that you certify the following:** ``` Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ``` In case of any doubt, the gatekeeper may ask you to certify the above in writing, i.e. via email or by including a `Signed-off-by:` line at the bottom of your commit comments. To improve tracking of who is the author of the contribution, we kindly ask you to use your real name (not an alias) when committing your changes to PMEMKV: ``` Author: Random J Developer ``` # Implementing persistent containers When developing a persistent container make sure you follow the rules and steps described here. ## Steps 1. Create container implementation 2. Create doc_snippet/example 3. Add TEST_CONTAINER CMake option for enabling/disabling container's testing. 4. Add tests (+ if possible, enable libcxx tests in tests/external/libcxx) ## Requirements: * Constructors should check whether the container is being constructed on pmem and within a transaction. If not, appropriate exception should be thrown. * If any operation has to or is not allowed to be called inside of a transaction there should be a proper check for that. * Operations which modify the entire container (like operator=, clear(), etc.) should be transactional. * If any operation inside destructor can fail there should be a separate method like free_data/destroy. * Each complex container should have a mechanism for checking layout compatibility. One way is to store size of key and value on pmem and compare it with sizeof(value_type) after pool reopen. * Padding should always be explicit. * If any object from standard library is being stored on pmem its size should be verified by static_assert. * Public methods should be documented using doxygen comments. ## Optional features: * for_each_ptr method for defragmentation purposes. * Containers with lower memory overhead (like vector) can implement some heuristic for verifying layout (like comparing pmemobj_alloc_usable_size with expected capacity). # Configuring GitHub fork To build and submit documentation as an automatically generated pull request, the repository has to be properly configured. * [Personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) for GitHub account has to be generated. * Such personal access token has to be set in in GitHub repository's [secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) as `DOC_UPDATE_GITHUB_TOKEN` variable. * `DOC_UPDATE_BOT_NAME` secret variable has to be set. In most cases it will be the same as GitHub account name. * `DOC_REPO_OWNER` secret variable has to be set. Name of GitHub account, which will be target to make an automatic pull request with documentation. In most cases it will be the same as GitHub account name. To enable automatic images pushing to GitHub Container Registry, following variables: * `CONTAINER_REG` existing environment variable (defined in workflow files, in .github/ directory) has to be updated to contain proper GitHub Container Registry address (to forking user's container registry), * `GH_CR_USER` secret variable has to be set up - an account (with proper permissions) to publish images to the Container Registry (tab **Packages** in your GH profile/organization). * `GH_CR_PAT` secret variable also has to be set up - Personal Access Token (with only read & write packages permissions), to be generated as described [here](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token#creating-a-token) for selected account (user defined in above variable). libpmemobj-cpp-1.13.0/ChangeLog000066400000000000000000000226061410000307300162400ustar00rootroot00000000000000Tue Jul 27 2021 Igor Chorążewicz * Version 1.13.0 This release introduces new concurrent data structure - MPSC queue and implements limited concurrency support for radix tree. New features: - Introduce experimental MPSC queue (pmem::obj::experimental::mpsc_queue) - Implement support for multi-reader single-writer concurrency in pmem::obj::experimental::radix_tree - Introduce basic_dram_inline_string which can be kept both on pmem and dram Bug fixes: - Fix radix_tree leaf layout to ensure proper key/value alignment Other changes: - Switch default CMake's build type from "Debug" to "RelWithDebInfo" it's relevant for a GitHub users (who may e.g. run some benchmarks) - Add std::initializer_list constructor to pmem::obj::array to mimic aggregate initialization post C++20 Tue Jul 06 2021 Łukasz Stolarczuk * Version 1.6.1 This release fixes minor bugs. This is the last patch release for libpmemobj-cpp 1.6 version. Maintenance of this version is no longer supported. Notable changes: - string: fix max_size() return value - allocation_flag: mark constructor as explicit - peristent_ptr: change ptr_offset_magic to be properly aligned - fix few headers' includes Mon Jun 28 2021 Łukasz Stolarczuk * Version 1.5.2 This release fixes minor bugs. This is the last patch release for libpmemobj-cpp 1.5 version. Maintenance of this version is no longer supported. Notable changes: - operator[] for contiguous_iterator takes signed integral instead of unsigned - throw an exception when pmemobj_mutex_unlock fail - fix crash when a previous transaction failed to start because of already taken lock. Mon Feb 15 2021 Igor Chorążewicz * Version 1.12 This release introduces new transaction handler type (flat_transaction) which solves https://github.com/pmem/libpmemobj-cpp/issues/516 (more information can be found in README). It also introduces several improvements and bugfixes for radix_tree as well as additional methods for pmem::obj::string_view. New features: - pmem::obj::flat_transaction - extend API for pmem::obj::string_view (relational operators, find, substr, copy, compare) Bug fixes: - make default bytes_view implementation in radix_tree work for wide characters - fix assign_val function in radix tree which incorrectly handled inline_string for CharT != char - fix use after free in radix_tree::erase method Other changes: - allow using any iterator which supports operator[], operator-() and operator--() in pmem::obj::slice Wed Sep 30 2020 Szymon Romik * Version 1.11 This release introduces a new experimental container - persistent radix_tree along with inline_string and string_view classes. It also introduces a new pointer type: self_relative_ptr with std::atomic specialization. New features: - experimental radix_tree container (single-threaded sorted map) - experimental inline_string class (class serves similar purpose to pmem::obj::string, but keeps the data within the same allocation as inline_string itself) - string_view class (support for compilers older than C++17) - experimental self_relative_ptr and std::atomic specialization (persistent smart ptr which encapsulates the self offsetted pointer and provides member access, dereference and array access operators - for some workloads it could be faster alternative for persistent_ptr) Optimizations: - optimizations for concurrent_map with self_relative_ptr Other changes: - missing constructors for basic_string class - conversion operator for basic_string class - ported libcxx's sorted map tests - lower and lower_eq methods for concurrent_map - missing constructor for concurrent_map (comparator as an argument) Thu May 28 2020 Szymon Romik * Version 1.10 This release introduces a new experimental container - persistent concurrent map (based on concurrent skiplist implementation). It also introduces some optimizations for existing containers and minor bug fixes. New features: - concurrent_map container - swap() method for basic_string Optimizations: - optimized clear() and erase() for trivial types in segment_vector - optimized move constructor and assignment for basic_string Bug Fixes: - fixed free_data() in concurrent_hash_map Fri Jan 31 2020 Szymon Romik * Version 1.9 This release moves segment_vector out of experimental namespace and directory. It means that abovementioned container is guaranteed to have stable API and on-media layout. It also introduces defragmentation functionality with new defrag class in pmem::detail namespace and helper classes (which currently reside in "detail" directory): enumerable_thread_specific and volatile_state. With this release, we also decreased restart time of concurrent_hash_map (with a usage of the enumerable_thread_specific feature). New features: - new methods for pmem::obj::string (find() and its overloads) - defragmentation feature as a separate class in pmem::obj namespace and support for the defragmentation in containers: concurrent_hash_map, vector, string - removed template parameters from persistent_ptr_base class (make it type agnostic) and moved to the public API - new methods for pmem::obj::concurrent_hash_map (insert_or_assign and its overloads) Optimizations: - bucket rehashing in concurrent_hash_map moved to transaction - faster concurrent_hash_map restart (with "persistent TLS") Other changes: - added GitHub Actions as an additional CI - added documentation and doc snippets with some usage examples - added compatibility tests for different libpmemobj-cpp versions Fri Jan 24 2020 Szymon Romik * Version 1.8.1 This release fixes minor bugs. Notable changes: - fix compilation error in concurrent_hash_map - fix possible deadlock in erase method in concurrent_hash_map Thu Oct 03 2019 Szymon Romik * Version 1.8 This release moves persistent array/vector/string/concurrent_hash_map out from experimental namespace and directory. It means that abovementioned containers are guaranteed to have stable API and on-media layout. They are placed now in include/libpmemobj++/container/ directory and pmem::obj namespace. This release introduces also a new experimental container - persistent segment vector with templated segment policies. New features: - experimental persistent segment vector container Bug fixes: - fixed insert method in persistent vector - fixed move assignment operator in persistent array Other changes: - extended error messages in exceptions - added examples with simplekv using persistent containers - added modifiers methods for persistent string - added template locks for concurrent_hash_map - added layout versioning for concurrent_hash_map Optimizations: - concurrent_hash_map insert method implemented with tx - optimized snapshotting in persistent vector/string Wed Jun 26 2019 Szymon Romik * Version 1.7 This release introduces new experimental container - persistent concurrent hashmap and persistent string with limited functionality. Experimental features: - persistent concurrent hashmap - persistent string (constructors and modifiers) Bug fixes: - add option to force define IS_TRIVIALLY_COPYABLE - mark allocation_flag constructor as explicit - add missing include to v.hpp Fri Mar 15 2019 Igor Chorążewicz * Version 1.6 This release introduces ctl support, allocation flags, snapshot method and new experimental persistent container - vector. New features: - add support for pmemobj_ctl_set/get/exec - expose allocation flags in make_persistent(_atomic) - transaction: add snapshot method Experimental features: - persistent vector container Other changes: - automatically start transaction inside pmem::obj::experimental::array modifier methods (assignment operators, swap and fill) - add const methods for pmem::obj::experimental::array - add Valgrind instrumentation support - remove experimental const_contiguous_iterator - add get with arguments method overload for v Bug fixes: - throw an exception when dropping pmem lock failed - fix crash when previous transaction failed to start - fix forwarding parameters to constructor in make_persistent_atomic Optimizations: - decrease number of persistent_ptr dereferences in make_persistent_array Tue Feb 19 2019 Marcin Ślusarz * Version 1.5.1 This release fixes minor bugs and improves documentation. Notable changes: - fix v swap, assignment operators and constructors - change conversion operator from T() to T&() in v<> - fix range_snapshotting initialization in array.hpp. - fix range_snapshotting_iterator behaviour for snapshot_size == 0. Fri Oct 26 2018 Marcin Ślusarz * Version 1.5 This is the first release of libpmemobj-cpp as a separate project. It introduces one persistent container - array, which has std::array like interface. Currently it is considered experimental and lives in experimental namespace. We have also cleaned up some function names that, in retrospect, were chosen poorly. Functions with old names are still there but are deprecated. Experimental features: - volatile resides on pmem class - persistent array container libpmemobj-cpp-1.13.0/LICENSE000066400000000000000000000041351410000307300154700ustar00rootroot00000000000000SPDX-License-Identifier: BSD-3-Clause Copyright 2018-2021, Intel Corporation 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 the copyright holder 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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. Everything in this source tree is covered by the above license with the following exceptions: * tests/external/libcxx which contain tests adapted from llvm libcxx, and is covered by license contained in that directory. * include/detail/ringbuf.hpp and tests/mpsc_queue/ringbuf.cpp contain ring buffer implementation and tests adapted from: https://github.com/rmind/ringbuf which is covered by licence included in those files. * include/detail/ebr.hpp contain EBR implementation adapted from: https://github.com/rmind/libqsbr which is covered by licence included in this file. libpmemobj-cpp-1.13.0/README.md000066400000000000000000000173241410000307300157460ustar00rootroot00000000000000# libpmemobj-cpp [![Build status](https://github.com/pmem/libpmemobj-cpp/workflows/CPP/badge.svg)](https://github.com/pmem/libpmemobj-cpp/actions) [![libpmemobj-cpp version](https://img.shields.io/github/tag/pmem/libpmemobj-cpp.svg)](https://github.com/pmem/libpmemobj-cpp/releases/latest) [![Coverity Scan Build Status](https://scan.coverity.com/projects/15911/badge.svg)](https://scan.coverity.com/projects/pmem-libpmemobj-cpp) [![Coverage Status](https://codecov.io/github/pmem/libpmemobj-cpp/coverage.svg?branch=master)](https://codecov.io/gh/pmem/libpmemobj-cpp/branch/master) [![Packaging status](https://repology.org/badge/tiny-repos/libpmemobj-cpp.svg)](https://repology.org/project/libpmemobj-cpp/versions) **libpmemobj-cpp** is a C++ binding for **libpmemobj** (a library which is a part of [PMDK collection](https://github.com/pmem/pmdk)). More implementation details can be found in [include/libpmemobj++/README.md](include/libpmemobj++/README.md). Latest releases can be found on the ["releases" tab](https://github.com/pmem/libpmemobj-cpp/releases). Up-to-date support/maintenance status of branches/releases is available on [pmem.io](https://pmem.io/libpmemobj-cpp). ## Compatibility note In libpmemobj 1.12 we introduced a new transaction handler type: [pmem::obj::flat_transaction](https://pmem.io/libpmemobj-cpp/master/doxygen/classpmem_1_1obj_1_1flat__transaction.html). By defining LIBPMEMOBJ_CPP_USE_FLAT_TRANSACTION you can make pmem::obj::transaction to be an alias to pmem::obj::flat_transaction. In 1.12 we have also changed the default behavior of containers' transactional methods. Now, in case of any failure within such method, the outer transaction (if any) will not be immediately aborted. Instead, an exception will be thrown, which will lead to transaction abort only if it's not caught before the outer tx scope ends. To change the behavior to the old one, you can set LIBPMEMOBJ_CPP_FLAT_TX_USE_FAILURE_RETURN macro to 0. Be aware that the old behavior can lead to segfaults in some cases (see tx_nested_struct_example in this [file](examples/transaction/transaction.cpp)). ## Table of contents 1. [Pre-built packages](#pre-built-packages) - [Windows](#windows) - [Ubuntu/Debian](#ubuntudebian) - [Fedora/RHEL](#fedorarhel) 2. [Dependencies](#dependencies) 3. [Linux build](#linux-build) - [Standard compilation](#standard-compilation) - [Developer compilation](#developer-compilation) - [Distribution package build](#distribution-package-build) - [Compilation with Valgrind instrumentation](#compilation-with-valgrind-instrumentation) 4. [Windows build](#windows-build) - [Install prerequisites via vcpkg](#install-prerequisites-via-vcpkg) - [Compilation with Visual Studio 2015](#compilation-with-visual-studio-2015) - [Compilation with Visual Studio 2017 or above](#compilation-with-visual-studio-2017-or-above) 5. [Extra CMake compilation flags](#extra-cmake-compilation-flags) 6. [Contact us](#contact-us) ## Pre-built packages The best way to install stable releases, tested on specific OS, is to use package manager. ### Windows The recommended and the easiest way to install **libpmemobj-cpp** on Windows is to use Microsoft's vcpkg. Vcpkg is an open source tool and ecosystem created for library management. For more information about vcpkg please see [vcpkg repository](https://github.com/microsoft/vcpkg#quick-start-windows). ```ps .\vcpkg.exe install libpmemobj-cpp:x64-windows ``` ### Ubuntu/Debian For installation on Debian-related distros please execute following commands: ``` # apt install libpmemobj-cpp-dev ``` ### Fedora/RHEL To install **libpmemobj-cpp** on Fedora or RedHat execute: ``` # dnf install libpmemobj++-devel ``` ## Dependencies You will need the following packages for compilation: - **cmake** >= 3.3 - **libpmemobj-dev(el)** >= 1.9 (https://pmem.io/pmdk/) - compiler with C++11 support - **gcc** >= 4.8.1 1 - **clang** >= 3.3 - **msbuild** >= 14 2 - for testing and development: - **valgrind-devel** (at best with [pmemcheck support](https://github.com/pmem/valgrind)) - **clang-format** 9.0 - **perl** - **libatomic** - for Windows compilation: - [**vcpkg**](https://github.com/microsoft/vcpkg#quick-start-windows) Required packages (or their names) for some OSes may differ. Some examples or scripts in this repository may require additional dependencies, but should not interrupt the build. See our **[Dockerfiles](utils/docker/images)** (used e.g. on our CI systems) to get an idea what packages are required to build the entire libpmemobj-cpp, with all tests and examples. >1 C++11 is supported in GCC since version 4.8.1, but it does not support expanding variadic template variables in lambda expressions, which is required to build persistent containers and is possible with GCC >= 4.9.0. If you want to build libpmemobj-cpp without testing containers, use flag TEST_XXX=OFF (separate flag for each container). >2 **radix_tree** is supported on Windows with MSBuild >=15 (Visual Studio at least 2017 is needed). Testing radix_tree can be disabled via CMake option (use -DTEST_RADIX_TREE=OFF). ## Linux build ### Standard compilation ``` $ mkdir build $ cd build $ cmake .. [-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=] $ make # make install ``` ### Developer compilation ```sh $ mkdir build $ cd build $ cmake .. -DCMAKE_BUILD_TYPE=Debug -DDEVELOPER_MODE=1 -DCHECK_CPP_STYLE=1 $ make $ ctest --output-on-failure ``` ### Distribution package build ```sh $ mkdir build $ cd build $ cmake .. -DCPACK_GENERATOR="$GEN" -DCMAKE_INSTALL_PREFIX=/usr $ make package ``` $GEN is type of package generator and can be RPM or DEB CMAKE_INSTALL_PREFIX must be set to a destination were packages will be installed ### Compilation with Valgrind instrumentation In order to build your application with libpmemobj-cpp and [pmemcheck](https://github.com/pmem/valgrind) / memcheck / helgrind / drd, Valgrind instrumentation must be enabled during compilation by adding flags: - LIBPMEMOBJ_CPP_VG_PMEMCHECK_ENABLED=1 for pmemcheck instrumentation - LIBPMEMOBJ_CPP_VG_MEMCHECK_ENABLED=1 for memcheck instrumentation - LIBPMEMOBJ_CPP_VG_HELGRIND_ENABLED=1 for helgrind instrumentation - LIBPMEMOBJ_CPP_VG_DRD_ENABLED=1 for drd instrumentation, or - LIBPMEMOBJ_CPP_VG_ENABLED=1 for all Valgrind instrumentations (including pmemcheck). If there are no memcheck / helgrind / drd / pmemcheck headers installed on your system, build will fail. ## Windows build ### Install prerequisites via vcpkg ```ps vcpkg install pmdk:x64-windows vcpkg integrate install ``` ### Compilation with Visual Studio 2015 ```ps cmake . -Bbuild -G "Visual Studio 14 2015 Win64" -DCMAKE_TOOLCHAIN_FILE="c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake" -DTEST_RADIX_TREE=OFF msbuild build/ALL_BUILD.vcxproj /m ``` ### Compilation with Visual Studio 2017 or above ```ps cmake . -Bbuild -G "Visual Studio 15 2017" -A "x64" -DCMAKE_TOOLCHAIN_FILE="c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake" msbuild build/ALL_BUILD.vcxproj /m ``` ## Extra CMake compilation flags For custom build you can use CMake flags to change build type, change C++ standard, enable/disable components or features for testing purposes. To list all CMake flags use the following: ```sh $ mkdir build $ cd build $ cmake .. $ cmake -LH ``` or just use graphical CMake frontend like **cmake-qt-gui** or **cmake-curses-gui**. ## Contact us For more information on this library, contact Igor Chorążewicz (igor.chorazewicz@intel.com), Piotr Balcer (piotr.balcer@intel.com) or post on our **#pmem** Slack channel using [this invite link](https://join.slack.com/t/pmem-io/shared_invite/enQtNzU4MzQ2Mzk3MDQwLWQ1YThmODVmMGFkZWI0YTdhODg4ODVhODdhYjg3NmE4N2ViZGI5NTRmZTBiNDYyOGJjYTIyNmZjYzQxODcwNDg) or [Google group](https://groups.google.com/group/pmem). libpmemobj-cpp-1.13.0/appveyor.yml000066400000000000000000000003511410000307300170470ustar00rootroot00000000000000version: 1.4.{build} os: Visual Studio 2017 platform: x64 environment: VCPKG_DEFAULT_TRIPLET: x64-windows GENERATOR: "Visual Studio 14 2015 Win64" configuration: - Debug - Release build_script: - exit 0 test_script: - exit 0 libpmemobj-cpp-1.13.0/benchmarks/000077500000000000000000000000001410000307300165755ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/benchmarks/CMakeLists.txt000066400000000000000000000040441410000307300213370ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause # Copyright 2020-2021, Intel Corporation if(MSVC_VERSION) add_flag(-W2) add_flag("-D_FORTIFY_SOURCE=2" RELEASE) else() add_flag(-Wall) add_flag("-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" RELEASE) endif() add_flag(-Wpointer-arith) add_flag(-Wsign-compare) add_flag(-Wunreachable-code-return) add_flag(-Wmissing-variable-declarations) add_flag(-fno-common) add_flag(-Wunused-macros) add_flag(-Wsign-conversion) add_flag(-Wno-maybe-uninitialized) add_flag(-ggdb DEBUG) add_flag(-DDEBUG DEBUG) include_directories(${LIBPMEMOBJ_INCLUDE_DIRS} .) link_directories(${LIBPMEMOBJ_LIBRARY_DIRS}) function(add_benchmark name) set(srcs ${ARGN}) prepend(srcs ${CMAKE_CURRENT_SOURCE_DIR} ${srcs}) add_executable(benchmark-${name} ${srcs}) target_link_libraries(benchmark-${name} ${LIBPMEMOBJ_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) endfunction() add_check_whitespace(benchmarks-cmake ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt) add_cppstyle(benchmarks-common ${CMAKE_CURRENT_SOURCE_DIR}/*.*pp) add_check_whitespace(benchmarks-common ${CMAKE_CURRENT_SOURCE_DIR}/*.*pp) add_cppstyle(benchmarks-concurrent_hash_map ${CMAKE_CURRENT_SOURCE_DIR}/concurrent_hash_map/*.*pp) add_check_whitespace(benchmarks-concurrent_hash_map ${CMAKE_CURRENT_SOURCE_DIR}/concurrent_hash_map/*.*pp) add_cppstyle(benchmarks-self-relative-pointer ${CMAKE_CURRENT_SOURCE_DIR}/self_relative_pointer/*.*pp) add_check_whitespace(benchmarks-self-relative-pointer ${CMAKE_CURRENT_SOURCE_DIR}/self_relative_pointer/*.*pp) add_cppstyle(benchmarks-radix_tree ${CMAKE_CURRENT_SOURCE_DIR}/radix/*.*pp) add_check_whitespace(benchmarks-radix_tree ${CMAKE_CURRENT_SOURCE_DIR}/radix/*.*pp) if (TEST_CONCURRENT_HASHMAP) add_benchmark(concurrent_hash_map_insert_open concurrent_hash_map/insert_open.cpp) endif() if (TEST_SELF_RELATIVE_POINTER) add_benchmark(self_relative_pointer_get self_relative_pointer/get.cpp) add_benchmark(self_relative_pointer_assignment self_relative_pointer/assignment.cpp) endif() if (TEST_RADIX_TREE) add_benchmark(radix_tree radix/radix_tree.cpp) endif() libpmemobj-cpp-1.13.0/benchmarks/concurrent_hash_map/000077500000000000000000000000001410000307300226175ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/benchmarks/concurrent_hash_map/insert_open.cpp000066400000000000000000000072231410000307300256540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* Copyright 2020-2021, Intel Corporation */ /* * insert_open.cpp -- this simple benchmark is used to measure time of * inserting specified number of elements and time of runtime_initialize(). */ #include #include #include #include #include #include #include #include #include #include #include "../measure.hpp" #ifndef _WIN32 #include #define CREATE_MODE_RW (S_IWUSR | S_IRUSR) #else #include #define CREATE_MODE_RW (S_IWRITE | S_IREAD) #endif static const std::string LAYOUT = "insert_open"; using key_type = pmem::obj::p; using value_type = pmem::obj::p; using persistent_map_type = pmem::obj::concurrent_hash_map; struct root { pmem::obj::persistent_ptr pptr; }; void insert(pmem::obj::pool &pop, size_t n_inserts, size_t n_threads) { auto map = pop.root()->pptr; assert(map != nullptr); map->runtime_initialize(); std::vector v; for (size_t i = 0; i < n_threads; i++) { v.emplace_back( [&](size_t tid) { int begin = tid * n_inserts; int end = begin + int(n_inserts); for (int i = begin; i < end; ++i) { persistent_map_type::value_type val(i, i); map->insert(val); } }, i); } for (auto &t : v) t.join(); assert(map->size() == n_inserts * n_threads); } void open(pmem::obj::pool &pop) { auto map = pop.root()->pptr; assert(map != nullptr); map->runtime_initialize(); assert(map->size() > 0); } int main(int argc, char *argv[]) { pmem::obj::pool pop; try { std::string usage = "usage: %s file-name "; if (argc < 3) { std::cerr << usage << std::endl; return 1; } auto mode = std::string(argv[2]); if (mode != "create" && mode != "open") { std::cerr << usage << std::endl; return 1; } if (mode == "create" && argc < 5) { std::cerr << usage << std::endl; return 1; } const char *path = argv[1]; if (mode == "create") { size_t n_inserts = std::stoull(argv[3]); size_t n_threads = std::stoull(argv[4]); if (n_inserts * n_threads == 0) { std::cerr << "n_inserts and n_threads must be > 0"; return 1; } try { auto pool_size = n_inserts * n_threads * sizeof(int) * 65 + 20 * PMEMOBJ_MIN_POOL; pop = pmem::obj::pool::create( path, LAYOUT, pool_size, CREATE_MODE_RW); pmem::obj::transaction::run(pop, [&] { pop.root()->pptr = pmem::obj::make_persistent< persistent_map_type>(); }); } catch (pmem::pool_error &pe) { std::cerr << "!pool::create: " << pe.what() << std::endl; return 1; } std::cout << measure([&] { insert(pop, n_inserts, n_threads); }) << "ms" << std::endl; } else { try { pop = pmem::obj::pool::open(path, LAYOUT); } catch (pmem::pool_error &pe) { std::cerr << "!pool::open: " << pe.what() << std::endl; return 1; } std::cout << measure([&] { open(pop); }) << "ms" << std::endl; } pop.close(); } catch (const std::logic_error &e) { std::cerr << "!pool::close: " << e.what() << std::endl; return 1; } catch (const std::exception &e) { std::cerr << "!exception: " << e.what() << std::endl; try { pop.close(); } catch (const std::logic_error &e) { std::cerr << "!exception: " << e.what() << std::endl; } return 1; } return 0; } libpmemobj-cpp-1.13.0/benchmarks/measure.hpp000066400000000000000000000005731410000307300207540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* Copyright 2020, Intel Corporation */ #include template static typename TimeUnit::rep measure(F &&func) { auto start = std::chrono::steady_clock::now(); func(); auto duration = std::chrono::duration_cast( std::chrono::steady_clock::now() - start); return duration.count(); } libpmemobj-cpp-1.13.0/benchmarks/radix/000077500000000000000000000000001410000307300177045ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/benchmarks/radix/radix_tree.cpp000066400000000000000000000164451410000307300225500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* Copyright 2021, Intel Corporation */ /** * radix_tree.cpp -- this simple benchmark is used to compare times of basic * operations in radix_tree and std::map */ #include #include #include #include #include #include #include #include "../measure.hpp" struct data { size_t index; size_t data_1, data_2; }; struct { size_t count = 10000; size_t sample_size = 100; size_t batch_size = 1000; } params; using value_type = struct data; using kv_type = pmem::obj::experimental::radix_tree; struct root { pmem::obj::persistent_ptr kv; }; static std::map mymap; void show_usage(char *argv[]) { std::cerr << "usage: " << argv[0] << " file-name [count] [batch_size] [sample_size]" << std::endl; } void print_time_per_element(std::string msg, std::chrono::nanoseconds::rep total_time, size_t n_elements) { if (n_elements == 0) { throw std::invalid_argument( "Benchmark failed, wrong params passed."); } std::cout << msg << static_cast(total_time) / n_elements << "ns" << std::endl; } /* prepare odd keys to check finding non-existing keys (in the containers will * be only even keys) */ std::vector gen_nonexisting_keys(size_t count, size_t sample_size) { size_t key; size_t key1; std::vector ret; ret.reserve(count / sample_size); for (size_t i = 0; i < (count / sample_size); ++i) { key = static_cast(rand()); key <<= 32; key1 = static_cast(rand()); key |= (key1 | 0x1); ret.emplace_back(key); } return ret; } std::vector gen_keys(size_t count) { size_t key; size_t key1; std::vector ret; ret.reserve(count); for (size_t i = 0; i < count; ++i) { /* only even keys will be insterted */ key = static_cast(rand()); key <<= 32; key1 = static_cast(rand()); key |= (key1 & 0x0); ret.emplace_back(key); } return ret; } /* insert_f must insert batch_size elements */ template void insert_elements_kv(F &&insert_f, const std::string &container) { std::chrono::nanoseconds::rep insert_time = 0; std::cout << "Inserting " << params.count << " elements..." << std::endl; for (size_t i = 0; i < params.count; i += params.batch_size) { insert_time += measure([&] { insert_f(i); }); } print_time_per_element("Average insert time: (" + container + "): ", insert_time, params.count); } void lookup_elements_kv(pmem::obj::pool pop, std::vector &keys) { auto r = pop.root(); std::cout << "Looking up " << params.count / params.sample_size << " elements..." << std::endl; kv_type::iterator res_radix; std::map::iterator res_map; auto radix_time = measure([&] { for (size_t i = 0; i < params.count; i += params.sample_size) res_radix = r->kv->find(keys[i]); }); print_time_per_element("Average access time (persistent radix tree): ", radix_time, params.count / params.sample_size); auto std_map_time = measure([&] { for (size_t i = 0; i < params.count; i += params.sample_size) res_map = mymap.find(keys[i]); }); print_time_per_element("Average access time (map): ", std_map_time, params.count / params.sample_size); } void lookup_ne_elements_kv(pmem::obj::pool pop, std::vector &non_existing_keys) { auto r = pop.root(); std::cout << "[Key not present] Looking up " << non_existing_keys.size() << " elements..." << std::endl; kv_type::iterator res_radix; std::map::iterator res_map; auto radix_time = measure([&] { for (auto &key : non_existing_keys) res_radix = r->kv->find(key); }); print_time_per_element( "[Key not present] Average access time (persistent radix tree): ", radix_time, non_existing_keys.size()); auto std_map_time = measure([&] { for (auto &key : non_existing_keys) { res_map = mymap.find(key); } }); print_time_per_element("[Key not present] Average access time (map): ", std_map_time, non_existing_keys.size()); } void remove_all_elements_kv(pmem::obj::pool pop, std::vector &keys) { auto r = pop.root(); std::cout << "Removing " << keys.size() << " elements..." << std::endl; auto radix_time = measure([&] { for (auto it = r->kv->begin(); it != r->kv->end();) it = r->kv->erase(it); }); print_time_per_element("Average remove time (persistent radix tree): ", radix_time, keys.size()); auto std_map_time = measure([&] { for (auto it = mymap.begin(); it != mymap.end();) { auto tmp_it = it++; mymap.erase(tmp_it); } }); print_time_per_element("Average remove time (map): ", std_map_time, keys.size()); } int main(int argc, char *argv[]) { if (argc < 2) { show_usage(argv); return 1; } const char *path = argv[1]; if (argc > 2) { params.count = std::stoul(argv[2]); if (params.count == 0) { std::cerr << "Number of the elements must be > 0" << std::endl; return 1; } } if (argc > 3) { params.batch_size = std::stoul(argv[3]); if (params.batch_size == 0) { std::cerr << "Batch size must be > 0" << std::endl; return 1; } } if (argc > 4) { params.sample_size = std::stoul(argv[4]); if (params.sample_size == 0) { std::cerr << "Sample size must be > 0" << std::endl; return 1; } } std::cout << "Radix benchmark, count: " << params.count << ", batch_size: " << params.batch_size << ", sample_size: " << params.sample_size << std::endl; srand(time(0)); pmem::obj::pool pop; try { pop = pmem::obj::pool::open(path, "radix"); auto r = pop.root(); if (r->kv == nullptr) { pmem::obj::transaction::run(pop, [&] { r->kv = pmem::obj::make_persistent(); }); } } catch (pmem::pool_error &e) { std::cerr << e.what() << std::endl << "To create pool run: pmempool create obj --layout=radix -s 1G path_to_pool" << std::endl; } catch (std::exception &e) { std::cerr << e.what() << std::endl; } auto non_existing_keys = gen_nonexisting_keys(params.count, params.sample_size); auto keys_to_insert = gen_keys(params.count); try { insert_elements_kv( [&](size_t start) { auto r = pop.root(); pmem::obj::transaction::run(pop, [&] { for (size_t i = start; i < start + params.batch_size; ++i) { value_type value{i, i + 1, i + 2}; r->kv->try_emplace( keys_to_insert[i], value); } }); }, "persistent radix tree"); insert_elements_kv( [&](size_t start) { for (size_t i = start; i < start + params.batch_size; ++i) { value_type map_value{i, i + 1, i + 2}; mymap.emplace(keys_to_insert[i], map_value); } }, "map"); lookup_elements_kv(pop, keys_to_insert); lookup_ne_elements_kv(pop, non_existing_keys); remove_all_elements_kv(pop, keys_to_insert); pop.close(); } catch (std::exception &e) { std::cerr << e.what() << std::endl; } catch (...) { std::cerr << "Unexpected exception" << std::endl; } return 0; } libpmemobj-cpp-1.13.0/benchmarks/readme.md000066400000000000000000000032271410000307300203600ustar00rootroot00000000000000# Benchmarks These benchmarks allow measuring some operations in the libpmemobj-cpp. Currently following benchmarks are available: - **concurrent_hash_map_insert_open**: this benchmark is used to measure time of inserting specified number of elements and time of `runtime_initialize()` in concurrent hash map. - **radix_tree**: this benchmark is used to compare times of basic operations in radix_tree and std::map. - **self_relative_pointer_assignment**: this benchmark is used to measure time of the assignment operator and the swap function for persistent_ptr and self_relative_ptr. - **self_relative_pointer_get**: this benchmark is used to measure time of accessing and changing a specified number of elements from a persistent array using self_relative_ptr and persistent_ptr. ## Compiling Follow build steps for your OS (as described in top-level README), just make sure that the BUILD_BENCHMARKS option is ON. To build all benchmarks (when you are in a build dir): ```sh $ cd benchmarks $ make ``` To build a certain benchmark (when you are in a build dir): ```sh $ cd benchmarks $ make benchmark- ``` ## Running **Warning:** >These benchmarks shouldn't be run in a production environment, because they can remove/modify existing data in the tested containers. Each benchmark can require various input parameters. If you want to see the usage of a certain benchmark, just run this benchmark's binary without any parameters, e.g. ```sh $ ./benchmark-radix_tree ``` For example radix_tree benchmark needs following parameters: file_name \[count] \[batch_size] \[sample_size]. Example execution: ```sh $ ./benchmark-radix_tree my_pool 20000 200 2000 ``` libpmemobj-cpp-1.13.0/benchmarks/self_relative_pointer/000077500000000000000000000000001410000307300231615ustar00rootroot00000000000000libpmemobj-cpp-1.13.0/benchmarks/self_relative_pointer/assignment.cpp000066400000000000000000000116361410000307300260440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* Copyright 2020-2021, Intel Corporation */ /* * assignment.cpp -- this benchmark is used to measure time of * the assignment operator and the swap function for persistent_ptr and * self_relative_ptr */ #include #include #include "../measure.hpp" #include #include #include #include #include #include #ifndef _WIN32 #include #define CREATE_MODE_RW (S_IWUSR | S_IRUSR) #else #include #define CREATE_MODE_RW (S_IWRITE | S_IREAD) #endif static const std::string LAYOUT = "assignment"; using value_type = std::size_t; using size_type = std::ptrdiff_t; template using persistent_ptr = pmem::obj::persistent_ptr; template using self_relative_ptr = pmem::obj::experimental::self_relative_ptr; template using vector = pmem::obj::vector; constexpr size_type ARR_SIZE = 1000; struct root { persistent_ptr[]> vec_pers_ptr; self_relative_ptr[]> vec_self_ptr; }; template