diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml deleted file mode 100644 index 9c1836720..000000000 --- a/.github/workflows/build_windows.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: build (windows) - -on: - push: - branches: - - master - pull_request: - branches: - - master - -jobs: - skip_duplicate: - name: 'Check whether to skip job' - continue-on-error: true - runs-on: ubuntu-latest - - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@master - with: - paths: '["tpie/"]' - - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - - build: - name: 'Build (Windows, ${{matrix.build_type}})' - runs-on: windows-latest - - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} - - strategy: - fail-fast: false - matrix: - build_type: [Release, Debug, ExtraDebug] - - steps: - # Git repo set up - - name: Checkout commit - uses: actions/checkout@v2 - - # Install dependencies - - name: Set up Developer Command Prompt (p1) - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - - name: Install dependencies - run: | - echo "================================" - echo "Boost" - choco install boost-msvc-14.2 - - - name: CMake + MSBuild - working-directory: ${{runner.workspace}} - run: | - cmake -E make_directory ${{github.workspace}}\build - cd ${{github.workspace}}\build - SET CXXFLAGS="%CXXFLAGS% -D_HAS_AUTO_PTR_ETC=1" - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 .. - - msbuild ALL_BUILD.vcxproj diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index f4f94c1e0..6f3338030 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -10,7 +10,7 @@ on: jobs: skip_duplicate: - name: 'Check whether to skip job' + name: 'Skip job?' continue-on-error: true runs-on: ubuntu-latest diff --git a/.github/workflows/test_linux.yml b/.github/workflows/test_linux.yml new file mode 100644 index 000000000..710ce925a --- /dev/null +++ b/.github/workflows/test_linux.yml @@ -0,0 +1,147 @@ +name: test (Linux) + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + check_skip: + name: 'Skip job? (Linux)' + continue-on-error: true + runs-on: ubuntu-latest + + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + paths: '["tpie/**", "test/**"]' + + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + + build_and_test: + name: 'Build + Test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' + runs-on: ${{ matrix.os }} + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip != 'true' }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 10, cxx: g++ } # oldest possible + - { cc: gcc, v: 11, cxx: g++ } # default + - { cc: gcc, v: 12, cxx: g++ } # newest + + # Clang Compiler + - { cc: clang, v: 11, cxx: clang++ } # oldest possible + - { cc: clang, v: 14, cxx: clang++ } # default + - { cc: clang, v: 15, cxx: clang++ } # newst possible + + env: + cc: ${{matrix.cc.cc}}-${{matrix.cc.v}} + cxx: ${{matrix.cc.cxx}}-${{matrix.cc.v}} + macro_flags: '-DLZ4_compress_default\(a,b,c,d\)=LZ4_compress\(a,b,c\)' + + steps: + # Git repo set up + - name: Checkout commit + uses: actions/checkout@v2 + + # Installation Linux + - name: Install dependencies + run: | + sudo apt update + + echo "================================" + echo "Compiler" + sudo apt install build-essential + sudo apt install ${{matrix.cc.cc}}-${{matrix.cc.v}} + + echo "================================" + echo "Boost" + sudo apt install libboost-all-dev + + echo "================================" + echo "Snappy" + sudo apt install libsnappy-dev + + echo "================================" + echo "LZ4" + sudo apt install liblz4-dev + + echo "================================" + echo "ZSTD" + export CC=${{env.cc}} + export CCX=${{env.cxx}} + export MACRO_FLAGS="${{env.macro_flags}}" + + git clone https://github.com/facebook/zstd + cd zstd + git checkout tags/v1.3.1 + sudo make install + + # CMake build and run + - name: CMake build + working-directory: ${{runner.workspace}} + run: | + export CC=${{env.cc}} + if [ "${{ matrix.cc.cc }}" != "gcc" ] ; + then + export CXX=${{env.cxx}} + fi + export MACRO_FLAGS="${{env.macro_flags}}" + + cmake -E make_directory ${{github.workspace}}/build + cd ${{github.workspace}}/build + cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 -D CMAKE_C_FLAGS="$MACRO_FLAGS" -D CMAKE_CXX_FLAGS="$MACRO_FLAGS" .. + + make -j2 + + - name: CTest run + working-directory: ${{github.workspace}}/build + run: ctest --timeout 30 + + # Check if tests are missing + - name: Check missing CTests + working-directory: ${{github.workspace}} + run: | + sudo apt install python3 python3-pip + pip install cmakeast + python3 scripts/check_missing_ctests.py + + skip: + name: 'Build + Test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' + runs-on: ubuntu-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip == 'true' }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 10, cxx: g++ } # oldest possible + - { cc: gcc, v: 11, cxx: g++ } # default + - { cc: gcc, v: 12, cxx: g++ } # newest + + # Clang Compiler + - { cc: clang, v: 11, cxx: clang++ } # oldest possible + - { cc: clang, v: 14, cxx: clang++ } # default + - { cc: clang, v: 15, cxx: clang++ } # newst possible + + steps: + - name: Echo skip + run: | + echo "Running unit tests is skipped" diff --git a/.github/workflows/test_mac.yml b/.github/workflows/test_mac.yml new file mode 100644 index 000000000..caa33fe96 --- /dev/null +++ b/.github/workflows/test_mac.yml @@ -0,0 +1,146 @@ +name: test (Mac OS) + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + check_skip: + name: 'Skip job? (Mac OS)' + continue-on-error: true + runs-on: ubuntu-latest + + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + paths: '["tpie/**", "test/**"]' + + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + + build_and_test: + name: 'Build + Test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' + runs-on: ${{ matrix.os }} + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip != 'true' }} + + strategy: + fail-fast: false + matrix: + os: [macos-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 7, cxx: g++, xcode: latest } + - { cc: gcc, v: 10, cxx: g++, xcode: latest } + - { cc: gcc, v: 12, cxx: g++, xcode: latest } + + # Clang Compiler + - { cc: clang, cxx: clang++, xcode: 13.1 } # oldest + - { cc: clang, cxx: clang++, xcode: 13.4 } + - { cc: clang, cxx: clang++, xcode: 14.0 } + - { cc: clang, cxx: clang++, xcode: 14.2 } # newest + + steps: + # Git repo set up + - name: Checkout commit + uses: actions/checkout@v2 + + # Install dependencies + - name: Install xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{matrix.cc.xcode}} + + - name: Install dependencies + run: | + brew update + + if ["${{matrix.cc.cc}}" == "gcc"]; + then + echo "================================" + echo "Compiler" + brew install ${{matrix.cc.cc}}@${{matrix.cc.v}} + fi + + echo "================================" + echo "Boost" + brew install boost + + echo "================================" + echo "Snappy" + brew install snappy + + echo "================================" + echo "LZ4" + brew install lz4 + + echo "================================" + echo "ZSTD" + brew install zstd + + # CMake build and run + - name: CMake build + working-directory: ${{runner.workspace}} + run: | + if [ "${{ matrix.cc.cc }}" == "gcc" ] ; + then + export CC=/usr/bin/${{matrix.cc.cc}} + export CXX=/usr/bin/${{matrix.cc.cxx}} + else + export CC=${{matrix.cc.cc}} + export CXX=${{matrix.cc.cxx}} + fi + + cmake -E make_directory ${{github.workspace}}/build + cd ${{github.workspace}}/build + cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 .. + + make -j2 + + - name: CTest run + working-directory: ${{github.workspace}}/build + run: ctest --timeout 30 + + # Check if tests are missing + - name: Check missing CTests + working-directory: ${{github.workspace}} + run: | + brew install python3 + pip3 install cmakeast + python3 scripts/check_missing_ctests.py + + skip: + name: 'Build + Test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' + runs-on: ubuntu-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip == 'true' }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + build_type: [Release, Debug] + cc: + # GNU Compiler + - { cc: gcc, v: 10, cxx: g++ } # oldest possible + - { cc: gcc, v: 11, cxx: g++ } # default + - { cc: gcc, v: 12, cxx: g++ } # newest + + # Clang Compiler + - { cc: clang, v: 11, cxx: clang++ } # oldest possible + - { cc: clang, v: 14, cxx: clang++ } # default + - { cc: clang, v: 15, cxx: clang++ } # newst possible + + steps: + - name: Echo skip + run: | + echo "Running unit tests is skipped" + diff --git a/.github/workflows/test_windows.yml b/.github/workflows/test_windows.yml new file mode 100644 index 000000000..668256ce5 --- /dev/null +++ b/.github/workflows/test_windows.yml @@ -0,0 +1,92 @@ +name: test (Windows) + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + check_skip: + name: 'Skip job? (Windows)' + continue-on-error: true + runs-on: ubuntu-latest + + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@master + with: + paths: '["tpie/**", "test/**"]' + + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + + build_and_test: + name: 'Build + Test (Windows, ${{matrix.build_type}})' + runs-on: windows-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip != 'true' }} + + strategy: + fail-fast: false + matrix: + build_type: [Release, Debug] + + steps: + # Git repo set up + - name: Checkout commit + uses: actions/checkout@v2 + + # Install dependencies + - name: Set up Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1.12.1 + with: + arch: x64 + + - name: Install Boost + uses: MarkusJx/install-boost@v2.3.0 + id: install-boost + with: + # List of all versions here: + # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json + boost_version: 1.79.0 + platform_version: 2019 + toolset: msvc + + # Build + - name: Configure CMake + NMake all + working-directory: ${{runner.workspace}} + run: | + cmake -E make_directory ${{github.workspace}}\build + cd ${{github.workspace}}\build + SET CXXFLAGS="%CXXFLAGS% -D_HAS_AUTO_PTR_ETC=1" + cmake -G "NMake Makefiles" -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=17 -D Boost_INCLUDE_DIR=${{env.BOOST_ROOT}}/include -D Boost_LIBRARY_DIRS=${{env.BOOST_ROOT}}/lib .. + nmake + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + + # Run unit tests + - name: CTest run + run: | + cd ${{github.workspace}}\build + ctest + + skip: + name: 'Build + Test (Windows, ${{matrix.build_type}})' + runs-on: ubuntu-latest + + needs: check_skip + if: ${{ needs.check_skip.outputs.should_skip == 'true' }} + + strategy: + fail-fast: false + matrix: + build_type: [Release, Debug] + + steps: + - name: Echo skip + run: | + echo "Running unit tests is skipped" diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml deleted file mode 100644 index eb1fec240..000000000 --- a/.github/workflows/unit_test.yml +++ /dev/null @@ -1,211 +0,0 @@ -name: unit tests - -on: - push: - branches: - - master - pull_request: - branches: - - master - -jobs: - skip_duplicate: - name: 'Check whether to skip job' - continue-on-error: true - runs-on: ubuntu-latest - - steps: - - id: skip_check - uses: fkirc/skip-duplicate-actions@master - with: - paths: '["tpie/", "test/"]' - - outputs: - should_skip: ${{ steps.skip_check.outputs.should_skip }} - - linux_test: - name: 'Unit test (Linux, ${{matrix.cc.cc}}-${{matrix.cc.v}}, ${{matrix.build_type}})' - runs-on: ${{ matrix.os }} - - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - build_type: [Release] #, Debug, ExtraDebug] - cc: - # GNU Compiler - - { cc: gcc, v: 7, cxx: g++ } # oldest possible - - { cc: gcc, v: 9, cxx: g++ } # default - - { cc: gcc, v: 10, cxx: g++ } # newest - - # Clang Compiler - - { cc: clang, v: 7, cxx: clang++ } # oldest possible - - { cc: clang, v: 11, cxx: clang++ } # newst possible - - env: - cc: ${{matrix.cc.cc}}-${{matrix.cc.v}} - cxx: ${{matrix.cc.cxx}}-${{matrix.cc.v}} - macro_flags: '-DLZ4_compress_default\(a,b,c,d\)=LZ4_compress\(a,b,c\)' - - steps: - # Git repo set up - - name: Checkout commit - uses: actions/checkout@v2 - - # Installation Linux - - name: Install dependencies - run: | - sudo apt update - - echo "================================" - echo "Compiler" - sudo apt install build-essential - sudo apt install ${{matrix.cc.cc}}-${{matrix.cc.v}} - - echo "================================" - echo "Boost" - sudo apt install libboost-all-dev - - echo "================================" - echo "Snappy" - sudo apt install libsnappy-dev - - echo "================================" - echo "LZ4" - sudo apt install liblz4-dev - - echo "================================" - echo "ZSTD" - export CC=${{env.cc}} - export CCX=${{env.cxx}} - export MACRO_FLAGS="${{env.macro_flags}}" - - git clone https://github.com/facebook/zstd - cd zstd - git checkout tags/v1.3.1 - sudo make install - - # CMake build and run - - name: CMake build - working-directory: ${{runner.workspace}} - run: | - export CC=${{env.cc}} - if [ "${{ matrix.cc.cc }}" != "gcc" ] ; - then - export CXX=${{env.cxx}} - fi - export MACRO_FLAGS="${{env.macro_flags}}" - - cmake -E make_directory ${{github.workspace}}/build - cd ${{github.workspace}}/build - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=14 -D CMAKE_C_FLAGS="$MACRO_FLAGS" -D CMAKE_CXX_FLAGS="$MACRO_FLAGS" .. - - make -j2 - - - name: CTest run - working-directory: ${{github.workspace}}/build - run: ctest --timeout 30 - - # Check if tests are missing - - name: Check missing CTests - working-directory: ${{github.workspace}} - run: | - sudo apt install python3 python3-pip - pip install cmakeast - python3 scripts/check_missing_ctests.py - - - macos_test: - name: 'Unit test (Mac OS, ${{matrix.cc.cc}}@${{matrix.cc.v || matrix.cc.xcode}}, ${{matrix.build_type}})' - runs-on: ${{ matrix.os }} - - needs: skip_duplicate - if: ${{ needs.skip_duplicate.outputs.should_skip != 'true' }} - - strategy: - fail-fast: false - matrix: - os: [macos-latest] - build_type: [Release] #, Debug, ExtraDebug] - cc: - # GNU Compiler - - { cc: gcc, v: 7, cxx: g++, xcode: latest } - - { cc: gcc, v: 10, cxx: g++, xcode: latest } - - # Clang Compiler - - { cc: clang, cxx: clang++, xcode: 11.7 } # oldest - - { cc: clang, cxx: clang++, xcode: 12.4 } - - { cc: clang, cxx: clang++, xcode: 13.1 } - - { cc: clang, cxx: clang++, xcode: 13.2 } # newest - - steps: - # Git repo set up - - name: Checkout commit - uses: actions/checkout@v2 - - # Install dependencies - - name: Install xcode - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{matrix.cc.xcode}} - - - name: Install dependencies - run: | - brew update - - if ["${{matrix.cc.cc}}" == "gcc"]; - then - echo "================================" - echo "Compiler" - brew install ${{matrix.cc.cc}}@${{matrix.cc.v}} - fi - - echo "================================" - echo "Boost" - brew install boost - - echo "================================" - echo "Snappy" - brew install snappy - - echo "================================" - echo "LZ4" - brew install lz4 - - echo "================================" - echo "ZSTD" - brew install zstd - - # CMake build and run - - name: CMake build - working-directory: ${{runner.workspace}} - run: | - if [ "${{ matrix.cc.cc }}" == "gcc" ] ; - then - export CC=/usr/bin/${{matrix.cc.cc}} - export CXX=/usr/bin/${{matrix.cc.cxx}} - else - export CC=${{matrix.cc.cc}} - export CXX=${{matrix.cc.cxx}} - fi - - cmake -E make_directory ${{github.workspace}}/build - cd ${{github.workspace}}/build - cmake -D CMAKE_BUILD_TYPE="${{matrix.build_type}}" -D CMAKE_CXX_STANDARD=14 .. - - make -j2 - - - name: CTest run - working-directory: ${{github.workspace}}/build - run: ctest --timeout 30 - - # Check if tests are missing - - name: Check missing CTests - working-directory: ${{github.workspace}} - run: | - brew install python3 - pip3 install cmakeast - python3 scripts/check_missing_ctests.py diff --git a/README.md b/README.md index ec8a31c96..f10e15be0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # TPIE - The Templated Portable I/O Environment [![LGPL-3.0 License](https://img.shields.io/badge/license-LGPL%203.0-blue.svg)](COPYING.md) -[![unit tests](https://github.com/thomasmoelhave/tpie/actions/workflows/unit_test.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/unit_test.yml) +[![test (Linux)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_linux.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_linux.yml) +[![test (Mac OS)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_macos.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_macos.yml) +[![test (Windows)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_windows.yml/badge.svg)](https://github.com/thomasmoelhave/tpie/actions/workflows/test_windows.yml) [![documentation](https://github.com/thomasmoelhave/tpie/actions/workflows/doxygen.yml/badge.svg)](https://thomasmoelhave.github.io/tpie) The TPIE (Templated Portable I/O Environment) library is a tool box providing @@ -35,7 +37,7 @@ hosted [there](http://www.madalgo.au.dk/tpie/doc/) and on ## Dependencies TPIE has a mandatory dependency on the _Boost_ library and requires a C++ -compiler that supports the _14_ standard (e.g. GNU 7+ and Clang 10+). +compiler that supports the _17_ standard (e.g. GNU 7+ and Clang 10+). Furthermore, optionally TPIE can use the _Snappy_, _LZ4_, and _ZSTD_ compression algorithms, if available. @@ -56,7 +58,7 @@ TPIE is then linked to each target executable of choice. ```cmake add_executable( ) target_link_libraries( tpie) -set_target_properties( PROPERTIES CXX_STANDARD 14) +set_target_properties( PROPERTIES CXX_STANDARD 17) ``` Then build your project with CMake. For other ways to install TPIE, see @@ -72,7 +74,7 @@ commands. # Compile entire TPIE project mkdir build cd build -cmake -D CXX_STANDARD 14 .. +cmake -D CXX_STANDARD 17 .. # Compile tests make @@ -93,7 +95,7 @@ CMake enabled examples in _apps_ execute the following commands # CMake mkdir build cd build -cmake -D CXX_STANDARD 14 .. +cmake -D CXX_STANDARD 17 .. # Compile cd apps// diff --git a/test/speed_regression/btree.cpp b/test/speed_regression/btree.cpp index 5c1f3a86f..8575786c4 100644 --- a/test/speed_regression/btree.cpp +++ b/test/speed_regression/btree.cpp @@ -19,7 +19,10 @@ #include "../app_config.h" #include "blocksize_2MB.h" + #include +#include + #include #include #include @@ -51,6 +54,9 @@ void test(size_t times, size_t size) { test_realtime_t start; test_realtime_t end; + std::random_device rd; + std::mt19937 gen(rd()); + for (size_t i = 0; i < times; ++i) { /*btree_internal_store store; btree > tree(store);*/ @@ -62,7 +68,7 @@ void test(size_t times, size_t size) { std::vector x(count); for(size_t i = 0; i < count; ++i) x[i] = i; - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); // insertion getTestRealtime(start); @@ -81,7 +87,7 @@ void test(size_t times, size_t size) { s(testRealtimeDiff(start,end)); // deletion - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); getTestRealtime(start); for(size_t i = 0; i < count; ++i) { diff --git a/test/unit/common.h b/test/unit/common.h index f4003126b..00aeb2365 100644 --- a/test/unit/common.h +++ b/test/unit/common.h @@ -38,7 +38,7 @@ struct bit_permute { }; template > -struct bit_pertume_compare: std::binary_function { +struct bit_pertume_compare { bit_permute bp; T c; typedef uint64_t first_argument_type; diff --git a/test/unit/test_btree.cpp b/test/unit/test_btree.cpp index 50ce64731..f739b7374 100644 --- a/test/unit/test_btree.cpp +++ b/test/unit/test_btree.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -94,7 +95,11 @@ bool basic_test(TA, A && ... a) { std::vector x(12); //34); std::iota(x.begin(), x.end(), 0); - std::random_shuffle(x.begin(), x.end()); + + std::random_device rd; + std::mt19937 gen(rd()); + + std::shuffle(x.begin(), x.end(), gen); for (size_t v: x) { tree.insert(v); @@ -103,7 +108,7 @@ bool basic_test(TA, A && ... a) { TEST_ENSURE_EQUALITY(tree2.size(), tree.size(), "The tree has the wrong size during insert stage."); } - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); for (size_t v: x) { tree.erase(v); tree2.erase(v); @@ -156,7 +161,10 @@ bool dynamic_iterator_test(TA ta, A && ... a) { for (int i=0; i < 1234; ++i) { x.push_back(i); } - std::random_shuffle(x.begin(), x.end()); + + std::random_device rd; + std::mt19937 gen(rd()); + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); @@ -219,16 +227,22 @@ bool key_and_comparator_test(TA, A && ... a) { TT...> tree(std::forward(a)..., comp); std::map, int, comparator > > tree2(comp); + std::random_device rd; + std::mt19937 gen(rd()); + std::vector x; for (int i=0; i < 1234; ++i) { item it; it.key.value = i; x.push_back(it); } - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=0; i < x.size(); ++i) x[i].value = i; - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); @@ -245,10 +259,12 @@ bool key_and_comparator_test(TA, A && ... a) { ++i2; } - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=0; i < x.size(); ++i) { tree.erase(x[i].key); } + return tree.empty(); } @@ -361,9 +377,15 @@ bool augment_test(TA ta, A && ... a) { default_comp c; ss_augmenter au; auto tree = get_btree(ta, c, au, std::forward(a)...); + + std::random_device rd; + std::mt19937 gen(rd()); + std::vector x; for (int i=0; i < 1234; ++i) x.push_back(i); - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); auto n=tree.root(); @@ -379,7 +401,9 @@ bool augment_test(TA ta, A && ... a) { } size_t e=x.size()/2; - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); + for (size_t i=e; i < x.size(); ++i) tree.erase(x[i]); x.resize(e); @@ -444,11 +468,15 @@ bool bound_test(TA, A && ... a) { btree tree(std::forward(a)...); set tree2; + std::random_device rd; + std::mt19937 gen(rd()); + std::vector x; for (int i=0; i < 1234; ++i) { x.push_back(i); } - std::random_shuffle(x.begin(), x.end()); + + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.insert(x[i]); @@ -464,7 +492,7 @@ bool bound_test(TA, A && ... a) { TEST_ENSURE(tree.upper_bound(r2) == tree.end() || *tree.upper_bound(r2) == *tree2.upper_bound(r2), "Upper bound compare failed during insert stage."); } - std::random_shuffle(x.begin(), x.end()); + std::shuffle(x.begin(), x.end(), gen); for (size_t i=0; i < x.size(); ++i) { tree.erase(x[i]); diff --git a/test/unit/test_close_file.cpp b/test/unit/test_close_file.cpp index cd446e4d3..b0312b6c1 100644 --- a/test/unit/test_close_file.cpp +++ b/test/unit/test_close_file.cpp @@ -30,6 +30,9 @@ #include #include +#include +#include + #ifdef WIN32 class open_file_monitor { public: @@ -44,8 +47,12 @@ class open_file_monitor { tpie::log_debug() << "Caught filesystem_error: " << e.what() << std::endl; // Already open? return false; + } catch (const std::system_error & e) { + tpie::log_debug() << "Caught (std) system_error: " << e.what() << std::endl; + // Already open? + return false; } catch (const boost::system::system_error & e) { - tpie::log_debug() << "Caught system_error: " << e.what() << std::endl; + tpie::log_debug() << "Caught (Boost) system_error: " << e.what() << std::endl; // Already open? return false; } diff --git a/test/unit/test_freespace_collection.cpp b/test/unit/test_freespace_collection.cpp index a9430a7ad..cd7634ce8 100644 --- a/test/unit/test_freespace_collection.cpp +++ b/test/unit/test_freespace_collection.cpp @@ -44,13 +44,38 @@ memory_size_type random(memory_size_type seed, memory_size_type min, memory_size return (seed * 1009) % (max - min) + min; } -int random_generator(int i) { - return 10007 % i; -} +class unrandom_generator +{ +public: + typedef unsigned int result_type; + + unrandom_generator() = default; + unrandom_generator(size_t /*n*/) { } + +private: + result_type mod = 0; + static constexpr result_type val = 10007; + +public: + constexpr static result_type min() + { return 0u; } + + constexpr static result_type max() + { return val; } + + result_type g() + { + if (++mod == val) { mod = 1; } + return val % mod; + } + + result_type operator()() + { return g(); } +}; bool alloc_test(memory_size_type size, memory_size_type block_size) { typedef std::vector handles_t; - temp_file file; + temp_file file; freespace_collection collection(file.path(), block_size); handles_t handles; @@ -87,7 +112,7 @@ bool size_test(memory_size_type size, memory_size_type block_size) { for(memory_size_type i = 0; i < size; ++i) { TEST_ENSURE(collection.size() >= minimum_size, "The space used is too small."); - + minimum_size += block_size; block_handle handle = collection.alloc(); @@ -96,8 +121,11 @@ bool size_test(memory_size_type size, memory_size_type block_size) { } // the two arrays are shuffled the same way - std::random_shuffle(handles.begin(), handles.end(), random_generator); - std::random_shuffle(sizes.begin(), sizes.end(), random_generator); + unrandom_generator g1; + std::shuffle(handles.begin(), handles.end(), g1); + + unrandom_generator g2; + std::shuffle(sizes.begin(), sizes.end(), g2); for(memory_size_type i = 0; i < size; ++i) { TEST_ENSURE(collection.size() >= minimum_size, "The space used is too small."); @@ -112,4 +140,4 @@ int main(int argc, char **argv) { return tpie::tests(argc, argv) .test(alloc_test, "alloc", "size", 1000, "block_size", 1024) .test(size_test, "size", "size", 1000, "block_size", 1024); -} \ No newline at end of file +} diff --git a/tpie/packed_array.h b/tpie/packed_array.h index 567d806ae..25f174cf9 100644 --- a/tpie/packed_array.h +++ b/tpie/packed_array.h @@ -1,19 +1,19 @@ // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*- // vi:set ts=4 sts=4 sw=4 noet : // Copyright 2008, The TPIE development team -// +// // This file is part of TPIE. -// +// // TPIE is free software: you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License as published by the // Free Software Foundation, either version 3 of the License, or (at your // option) any later version. -// +// // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public // License for more details. -// +// // You should have received a copy of the GNU Lesser General Public License // along with TPIE. If not, see #ifndef __TPIE_PACKED_ARRAY_H__ @@ -31,66 +31,159 @@ namespace tpie { -///////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// /// \internal /// \brief Base class for the iterators +/// /// \tparam CT CRTP child class +/// /// \tparam forward Is this a forward iterator? -///////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// template -class packed_array_iter_facade { +class packed_array_iter_facade +{ private: - CT & self() {return *reinterpret_cast(this);} template friend class packed_array_iter_facade; + /////////////////////////////////////////////////////////////////////////// + /// \brief Reference to `this` as the CRTP class `CT`. + /////////////////////////////////////////////////////////////////////////// + CT & self() + { return *reinterpret_cast(this); } + public: - const CT & self() const {return *reinterpret_cast(this);} + /////////////////////////////////////////////////////////////////////////// + const CT & self() const + { return *reinterpret_cast(this); } + /////////////////////////////////////////////////////////////////////////// typedef ptrdiff_t difference_type; + + /////////////////////////////////////////////////////////////////////////// typedef std::random_access_iterator_tag iterator_category; + + /////////////////////////////////////////////////////////////////////////// template - bool operator==(const TT & o) const {return (self()-o) == 0;} + bool operator==(const TT & o) const + { return (self()-o) == 0; } + + /////////////////////////////////////////////////////////////////////////// template - bool operator!=(const TT & o) const {return (self()-o) != 0;} - CT & operator++() {self().index() += forward?1:-1; return self();} - CT operator++(int) {CT x=self(); ++self(); return x;} - CT & operator--() {self().index() += forward?-1:1; return self();} - CT operator--(int) {CT x=self(); --self(); return x;} - bool operator<(const CT & o) const {return (self()-o) < 0;} - bool operator>(const CT & o) const {return (self()-o) > 0;} - bool operator<=(const CT & o) const {return (self()-o) <= 0;} - bool operator>=(const CT & o) const {return (self()-o) >= 0;} - ptrdiff_t operator-(const CT & o) const {return forward ? (self().index() - o.index()) : (o.index() - self().index());} - CT operator+(difference_type n) const {CT x=self(); return x += n;} - CT operator-(difference_type n) const {CT x=self(); return x -= n;} - CT & operator+=(difference_type n) {self().index() += (forward?n:-n); return self();} - CT & operator-=(difference_type n) {self().index() += (forward?n:-n); return self();} - RT operator[](difference_type n) {return *(self() + n);} + bool operator!=(const TT & o) const + { return (self()-o) != 0; } + + /////////////////////////////////////////////////////////////////////////// + CT & operator++() + { + self().index() += forward ? 1 : -1; + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + CT operator++(int) + { + CT x = self(); + ++self(); + return x; + } + + /////////////////////////////////////////////////////////////////////////// + CT & operator--() + { + self().index() += forward ? -1 : 1; + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + CT operator--(int) + { + CT x = self(); + --self(); + return x; + } + + /////////////////////////////////////////////////////////////////////////// + bool operator<(const CT & o) const + { return (self()-o) < 0; } + + /////////////////////////////////////////////////////////////////////////// + bool operator>(const CT & o) const + { return (self()-o) > 0; } + + /////////////////////////////////////////////////////////////////////////// + bool operator<=(const CT & o) const + { return (self()-o) <= 0; } + + /////////////////////////////////////////////////////////////////////////// + bool operator>=(const CT & o) const + { return (self()-o) >= 0; } + + /////////////////////////////////////////////////////////////////////////// + difference_type operator-(const CT & o) const + { return forward ? (self().index() - o.index()) : (o.index() - self().index()); } + + /////////////////////////////////////////////////////////////////////////// + CT operator+(difference_type n) const + { + CT x = self(); + return x += n; + } + + /////////////////////////////////////////////////////////////////////////// + CT operator-(difference_type n) const + { + CT x = self(); + return x -= n; + } + + /////////////////////////////////////////////////////////////////////////// + CT & operator+=(difference_type n) + { + self().index() += (forward?n:-n); + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + CT & operator-=(difference_type n) + { + self().index() += (forward?n:-n); + return self(); + } + + /////////////////////////////////////////////////////////////////////////// + RT operator[](difference_type n) + { + return *(self() + n); + } }; +/////////////////////////////////////////////////////////////////////////////// template -CT operator+(ptrdiff_t n, const packed_array_iter_facade & i) { +CT operator+(ptrdiff_t n, const packed_array_iter_facade & i) +{ CT tmp(i.self()); tmp += n; return tmp; } -/////////////////////////////////////////////////////////////////////////// -/// \brief An array storring elements of type T using B -/// bits to to store a element. +/////////////////////////////////////////////////////////////////////////////// +/// \brief An array storing elements of type T using B bits to store an element. /// -/// T must be either bool or int. B must devide the word size, (XXX why?) -/// in reality only 1, 2 or 4 seems usamle +/// \tparam T The type of elements to store in the array. This has to be `bool` +/// or `int`. /// -/// \tparam T The type of elements to store in the array -/// \tparam B The number of bits used to store a single element -/////////////////////////////////////////////////////////////////////////// +/// \tparam B The number of bits used to store a single element. This value must +/// divide the word size, so it can in reality only be 1, 2, or 4. +/////////////////////////////////////////////////////////////////////////////// template -class packed_array: public linear_memory_base >{ +class packed_array + : public linear_memory_base > +{ public: typedef size_t storage_type; + private: - // TODO is this necessary? + // TODO: is this necessary? Can we slack this requirement to store more? static_assert(sizeof(storage_type) * 8 % B == 0, "Bad storrage"); /////////////////////////////////////////////////////////////////////////// @@ -128,364 +221,537 @@ class packed_array: public linear_memory_base >{ return (1 << B)-1; } + /////////////////////////////////////////////////////////////////////////// template class const_iter_base; + /////////////////////////////////////////////////////////////////////////// template class iter_base; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \internal - /// \brief Iterator and reverse iterator will return an element - /// of this type, it can be cast to a T, and assigned a T value - ///////////////////////////////////////////////////////// + /// + /// \brief Iterator and reverse iterator will return an element of this + /// type, it can be cast to a T, and assigned a T value + /////////////////////////////////////////////////////////////////////////// class iter_return_type { private: - iter_return_type(storage_type * e, size_t i): elms(e), index(i) {} + template friend class packed_array; + storage_type * elms; size_t index; + + iter_return_type(storage_type * e, size_t i) + : elms(e), index(i) + { } public: - template friend class packed_array; - operator T() const {return static_cast((elms[high(index)] >> low(index))&mask());} - iter_return_type & operator=(const T b) { + /////////////////////////////////////////////////////////////////////// + operator T() const + { return static_cast((elms[high(index)] >> low(index))&mask()); } + + /////////////////////////////////////////////////////////////////////// + iter_return_type & operator=(const T b) + { storage_type * p = elms+high(index); size_t i = low(index); *p = (*p & ~(mask()< - class iter_base: public packed_array_iter_facade, forward, iter_return_type> { + class iter_base + : public packed_array_iter_facade, forward, iter_return_type> + { private: - iter_return_type elm; - friend class const_iter_base; friend class packed_array; template friend class packed_array_iter_facade; - iter_base(storage_type * elms, size_t index): elm(elms, index) {}; - size_t & index() {return elm.index;} - const size_t & index() const {return elm.index;} + iter_return_type elm; + + /////////////////////////////////////////////////////////////////////// + iter_base(storage_type * elms, size_t index) + : elm(elms, index) + { } + + /////////////////////////////////////////////////////////////////////// + size_t & index() + { return elm.index; } + + /////////////////////////////////////////////////////////////////////// + const size_t & index() const + { return elm.index; } + public: typedef iter_return_type value_type; typedef iter_return_type & reference; typedef iter_return_type * pointer; - - iter_return_type & operator*() {return elm;} - iter_return_type * operator->() {return &elm;} - iter_base & operator=(const iter_base & o) {elm.index = o.elm.index; elm.elms=o.elm.elms; return *this;} - iter_base(iter_base const &o): elm(o.elm) {}; + + /////////////////////////////////////////////////////////////////////// + iter_return_type & operator*() + { return elm; } + + /////////////////////////////////////////////////////////////////////// + iter_return_type & operator*() const + { return const_cast(elm); } + + /////////////////////////////////////////////////////////////////////// + iter_return_type * operator->() + { return &elm; } + + /////////////////////////////////////////////////////////////////////// + iter_return_type * operator->() const + { return &elm; } + + /////////////////////////////////////////////////////////////////////// + iter_base & operator=(const iter_base & o) + { + elm.index = o.elm.index; + elm.elms=o.elm.elms; + return *this; + } + + /////////////////////////////////////////////////////////////////////// + iter_base(iter_base const &o) + : elm(o.elm) + { } }; - + + /////////////////////////////////////////////////////////////////////////// + /// \internal + /// + /// Added in `c9d7154f0` (10th of May, 2011) as a quick fix in Visual + /// Studio. Given the date, this was version 10.0 or earlier. This + /// workaround is not necessary anymore with Visual Studio 2019+ and hence + /// can be reverted (at the cost of slightly breaking backwards + /// compatibility). + /////////////////////////////////////////////////////////////////////////// typedef T vssucks; - ///////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// /// \internal - /// \brief Base class for const ierator and const reverse iterator + /// + /// \brief Base class for const iterator and const reverse iterator + /// /// \tparam forward Is this a forward iterator? - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// template - class const_iter_base: public packed_array_iter_facade, forward, vssucks> { + class const_iter_base + : public packed_array_iter_facade, forward, vssucks> + { private: - const storage_type * elms; - size_t idx; - friend class packed_array; friend class boost::iterator_core_access; template friend class packed_array_iter_facade; - const_iter_base(const storage_type * e, size_t i): elms(e), idx(i) {} - size_t & index() {return idx;} - const size_t & index() const {return idx;} + const storage_type * elms; + size_t idx; + + /////////////////////////////////////////////////////////////////////// + const_iter_base(const storage_type * e, size_t i) + : elms(e), idx(i) + { } + + /////////////////////////////////////////////////////////////////////// + size_t & index() + { return idx; } + + /////////////////////////////////////////////////////////////////////// + const size_t & index() const + { return idx; } + public: typedef vssucks value_type; typedef vssucks reference; typedef vssucks * pointer; - const_iter_base & operator=(const const_iter_base & o) {idx = o.idx; elms=o.elms; return *this;} - vssucks operator*() const {return static_cast(elms[high(idx)] >> low(idx) & mask());} - const_iter_base(const_iter_base const& o): elms(o.elms), idx(o.idx) {} - const_iter_base(iter_base const& o): elms(o.elm.elms), idx(o.elm.index) {} - }; + /////////////////////////////////////////////////////////////////////// + const_iter_base & operator=(const const_iter_base & o) + { + idx = o.idx; + elms=o.elms; + return *this; + } + + /////////////////////////////////////////////////////////////////////// + vssucks operator*() const + { return static_cast(elms[high(idx)] >> low(idx) & mask()); } + /////////////////////////////////////////////////////////////////////// + const_iter_base(const_iter_base const& o) + : elms(o.elms), idx(o.idx) + { } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + const_iter_base(iter_base const& o) + : elms(o.elm.elms), idx(o.elm.index) + { } + }; + + /////////////////////////////////////////////////////////////////////////// /// \internal - /// \brief This type is returned by the [] operator. - /// It can be cast to a T, and assigned a T value. - ///////////////////////////////////////////////////////// - struct return_type{ + /// + /// \brief Type of values returned by the [] operator. + /// + /// \details It can be cast to a T, and assigned a T value. That is, this + /// abstracts away packing and unpacking of logical values into and out of + /// the physical value that stores them. + /////////////////////////////////////////////////////////////////////////// + struct return_type + { private: - storage_type * p; - size_t i; - return_type(storage_type * p_, size_t i_): p(p_), i(i_) {} friend class packed_array; + + storage_type * p; + size_t i; + + /////////////////////////////////////////////////////////////////////// + return_type(storage_type * p_, size_t i_) + : p(p_), i(i_) + { } + public: - operator T() const {return static_cast((*p >> i) & mask());} - return_type & operator=(const T b) { + /////////////////////////////////////////////////////////////////////// + operator T() const + { return static_cast((*p >> i) & mask()); } + + /////////////////////////////////////////////////////////////////////// + return_type & operator=(const T b) + { *p = (*p & ~(mask()<(b) & mask()) << i); - return *this; + return *this; + } + + /////////////////////////////////////////////////////////////////////// + return_type & operator=(const return_type & t) + { + *this = (T) t; + return *this; } - return_type & operator=(const return_type & t){ - *this = (T) t; - return *this; - } }; storage_type * m_elements; size_t m_size; -public: - ///////////////////////////////////////////////////////// + +public: + /////////////////////////////////////////////////////////////////////////// /// \brief Type of values containd in the array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef T value_type; - - ///////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// /// \brief Iterator over a const array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef const_iter_base const_iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Reverse iterator over a const array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef const_iter_base const_reverse_iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Iterator over an array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef iter_base iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Reverse iterator over an array - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// typedef iter_base reverse_iterator; - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \copybrief linear_memory_structure_doc::memory_coefficient() /// \copydetails linear_memory_structure_doc::memory_coefficient() - ///////////////////////////////////////////////////////// - static double memory_coefficient(){ - return B/8.0; - } - - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + static double memory_coefficient() + { return B/8.0; } + + /////////////////////////////////////////////////////////////////////////// /// \copybrief linear_memory_structure_doc::memory_overhead() /// \copydetails linear_memory_structure_doc::memory_overhead() - ///////////////////////////////////////////////////////// - static double memory_overhead() { - return (double)sizeof(packed_array)+(double)sizeof(storage_type); - } + /////////////////////////////////////////////////////////////////////////// + static double memory_overhead() + { return (double)sizeof(packed_array)+(double)sizeof(storage_type); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Construct array of given size. /// - /// The elements have undefined values + /// \details The elements have undefined values + /// /// \param s The number of elements in the array - ///////////////////////////////////////////////////////// - packed_array(size_t s=0): m_elements(nullptr), m_size(0) {resize(s);} + /////////////////////////////////////////////////////////////////////////// + packed_array(size_t s = 0) + : m_elements(nullptr), m_size(0) + { resize(s); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Construct array of given size. /// /// \param s The number of elements in the array + /// /// \param value Each entry of the array is initialized with this value - ///////////////////////////////////////////////////////// - packed_array(size_t s, T value): m_elements(nullptr), m_size(0) {resize(s,value);} + /////////////////////////////////////////////////////////////////////////// + packed_array(size_t s, T value) + : m_elements(nullptr), m_size(0) + { resize(s,value); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Construct a copy of another array + /// /// \param a The array to copy - ///////////////////////////////////////////////////////// - packed_array(const packed_array & a): m_elements(nullptr), m_size(0) {*this=a;} + /////////////////////////////////////////////////////////////////////////// + packed_array(const packed_array & a) + : m_elements(nullptr), m_size(0) + { *this=a; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Move another aray into me + /// /// \param a The array to copy - ///////////////////////////////////////////////////////// - packed_array(packed_array && a): m_elements(a.m_elements), m_size(a.m_size) { + /////////////////////////////////////////////////////////////////////////// + packed_array(packed_array && a) + : m_elements(a.m_elements), m_size(a.m_size) + { a.m_elements = nullptr; a.m_size = 0; } - - ///////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////// /// \brief Free up all memory used by the array - ///////////////////////////////////////////////////////// - ~packed_array() {resize(0);} + /////////////////////////////////////////////////////////////////////////// + ~packed_array() + { resize(0); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Copy elements from another array into this. /// /// Note this array is resized to the size of other /// \param a The array to copy from /// \return a reference to this array - ///////////////////////////////////////////////////////// - packed_array & operator=(const packed_array & a) { + /////////////////////////////////////////////////////////////////////////// + packed_array & operator=(const packed_array & a) + { resize(a.m_size); for(size_t i=0;i(words(m_size)):nullptr; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Fill the entier array with the given value /// /// \param value the initialization element - ///////////////////////////////////////////////////////// - void fill(T value) { + /////////////////////////////////////////////////////////////////////////// + void fill(T value) + { storage_type x=0; - for (size_t i=0; i < perword(); ++i) + for (size_t i=0; i < perword(); ++i) x = (x << B) + ((storage_type)value & mask()); for (size_t i=0; i < words(m_size); ++i) - m_elements[i] = x; + m_elements[i] = x; } - - - ///////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////////////// /// \brief Change the size of the array /// - /// All elements are lost, after resize the value of the entries - /// is initialized by a copy of elm + /// All elements are lost, after resize the value of the entries is + /// initialized by a copy of elm + /// /// \param s the new size of the array + /// /// \param value the initialization element - ///////////////////////////////////////////////////////// - void resize(size_t s, T value) { + /////////////////////////////////////////////////////////////////////////// + void resize(size_t s, T value) + { resize(s); fill(value); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return the size of the array /// /// \return the size of the array - ///////////////////////////////////////////////////////// - size_t size() const {return m_size;} + /////////////////////////////////////////////////////////////////////////// + size_t size() const + { return m_size; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Check if the array is empty /// /// \return true if and only if size is 0 - ///////////////////////////////////////////////////////// - bool empty() const {return m_size ==0;} + /////////////////////////////////////////////////////////////////////////// + bool empty() const + { return m_size ==0; } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an array entry /// /// \param i the index of the entry to return + /// /// \return the array entry - ///////////////////////////////////////////////////////// - T operator[](size_t i)const { + /////////////////////////////////////////////////////////////////////////// + T operator[](size_t i) const + { assert(i < m_size); return static_cast((m_elements[high(i)] >> low(i))&mask()); - } - - ///////////////////////////////////////////////////////// + } + + /////////////////////////////////////////////////////////////////////////// /// \brief Return a object behaving like a reference to an array entry /// /// \param i the index of the entry to return + /// /// \return The object behaving like a reference - ///////////////////////////////////////////////////////// - return_type operator[](size_t i) { + /////////////////////////////////////////////////////////////////////////// + return_type operator[](size_t i) + { assert(i < m_size); return return_type(m_elements+high(i), low(i)); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an iterator to the i'th element of the array /// /// \param i the index of the element we want an iterator to + /// /// \return an iterator to the i'th element - ///////////////////////////////////////////////////////// - iterator find(size_type i) {return iterator(m_elements,i);} + /////////////////////////////////////////////////////////////////////////// + iterator find(size_type i) + { return iterator(m_elements,i); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a const iterator to the i'th element of the array /// /// \param i the index of the element we want an iterator to + /// /// \return a const iterator to the i'th element - ///////////////////////////////////////////////////////// - const_iterator find(size_type i) const {return const_iterator(m_elements,i);} + /////////////////////////////////////////////////////////////////////////// + const_iterator find(size_type i) const + { return const_iterator(m_elements,i); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an iterator to the beginning of the array /// - /// \return an iterator tho the beginning of the array - ///////////////////////////////////////////////////////// - iterator begin() {return iterator(m_elements,0);} + /// \return an iterator to the beginning of the array + /////////////////////////////////////////////////////////////////////////// + iterator begin() + { return iterator(m_elements,0); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a const iterator to the beginning of the array /// - /// \return a const iterator tho the beginning of the array - ///////////////////////////////////////////////////////// - const_iterator begin() const {return const_iterator(m_elements,0);} + /// \return a const iterator to the beginning of the array + /////////////////////////////////////////////////////////////////////////// + const_iterator begin() const + { return const_iterator(m_elements,0); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return an iterator to the end of the array /// - /// \return an iterator tho the end of the array - ///////////////////////////////////////////////////////// - iterator end() {return iterator(m_elements,m_size);} + /// \return an iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + iterator end() + { return iterator(m_elements,m_size); } - ///////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// /// \brief Return a const iterator to the end of the array /// - /// \return a const iterator tho the end of the array - ///////////////////////////////////////////////////////// - const_iterator end() const {return const_iterator(m_elements,m_size);} + /// \return a const iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + const_iterator end() const + { return const_iterator(m_elements,m_size); } + + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a reverse iterator to the beginning of the array + /// + /// \return a reverse iterator to the beginning of the array + /// + /// \internal We use m_elements -1 as basis for the reverse operators To + // make sure that the index of rend is positive + /////////////////////////////////////////////////////////////////////////// + reverse_iterator rbegin() + { return reverse_iterator(m_elements-1, perword()+m_size-1); } + + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a const reverse iterator to the beginning of the array + /// + /// \return a reverse iterator to the beginning of the array + /////////////////////////////////////////////////////////////////////////// + const_reverse_iterator rbegin() const + { return const_reverse_iterator(m_elements-1, perword()+m_size-1); } - //We use m_elements -1 as basic for the reverse operators - //To make sure that the index of rend is positive - reverse_iterator rbegin() {return reverse_iterator(m_elements-1, perword()+m_size-1);} - const_reverse_iterator rbegin() const {return const_reverse_iterator(m_elements-1, perword()+m_size-1);} - reverse_iterator rend() {return reverse_iterator(m_elements-1, perword()-1);} - const_reverse_iterator rend() const {return const_reverse_iterator(m_elements-1, perword()-1);} + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a reverse iterator to the end of the array + /// + /// \return a const reverse iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + reverse_iterator rend() + { return reverse_iterator(m_elements-1, perword()-1); } + + /////////////////////////////////////////////////////////////////////////// + /// \brief Return a const reverse iterator to the end of the array + /// + /// \return a const reverse iterator to the end of the array + /////////////////////////////////////////////////////////////////////////// + const_reverse_iterator rend() const + { return const_reverse_iterator(m_elements-1, perword()-1); } /////////////////////////////////////////////////////////////////////////// /// \brief Swap two arrays. /////////////////////////////////////////////////////////////////////////// - void swap(packed_array & o) { + void swap(packed_array & o) + { std::swap(m_elements, o.m_elements); std::swap(m_size, o.m_size); } }; +} // namespace tpie -} //namespace tpie - -namespace std { +namespace std +{ template -void swap(tpie::packed_array & a, tpie::packed_array & b) { +void swap(tpie::packed_array & a, tpie::packed_array & b) +{ a.swap(b); } -} //namespace std +} // namespace std + #endif //__TPIE_PACKED_ARRAY_H__ diff --git a/tpie/pipelining/merge_sorter.cpp b/tpie/pipelining/merge_sorter.cpp index 89245a529..50f24b140 100644 --- a/tpie/pipelining/merge_sorter.cpp +++ b/tpie/pipelining/merge_sorter.cpp @@ -317,12 +317,14 @@ void merge_sorter_base::calculate_parameters() { // Phase 1 (run formation): // Run length: determined by the number of items we can hold in memory. // Fanout: unbounded - - memory_size_type streamMemory = m_element_file_stream_memory_usage; - memory_size_type tempFileMemory = 2*p.fanout*sizeof(temp_file); + + const memory_size_type streamMemory = m_element_file_stream_memory_usage; + const memory_size_type tempFileMemory = 2*p.fanout*sizeof(temp_file); log_pipe_debug() << "Phase 1: " << p.memoryPhase1 << " b available memory; " << streamMemory << " b for a single stream; " << tempFileMemory << " b for temp_files\n"; - memory_size_type min_m1 = std::max(128*1024UL, 16*m_item_size) + bits::run_positions::memory_usage() + streamMemory + tempFileMemory; + const memory_size_type minRunLength = std::max(128*1024UL, 16*m_item_size); + const memory_size_type min_m1 = minRunLength + bits::run_positions::memory_usage() + streamMemory + tempFileMemory; + if (p.memoryPhase1 < min_m1) { log_warning() << "Not enough phase 1 memory for 128 KB items and an open stream! (" << p.memoryPhase1 << " < " << min_m1 << ")\n"; p.memoryPhase1 = min_m1;