Compare commits

...
Author SHA1 Message Date
Boyarinov, Konstantin 0b6365732a Commit more semantics support 2021-06-29 11:14:36 +03:00
Boyarinov, Konstantin 68c6b62b4b Add parallel_for invoke semantics 2021-06-24 12:08:56 +03:00
Anton Potapov ec505c7d5a Workaround GCC 11 warning in concurrent_unordered_base (#447)
Signed-off-by: Anton Potapov <anton.potapov@intel.com>
2021-06-22 12:16:57 +03:00
Ivan KochinandAnton Potapov e1b24895e6 SOM example: enable mandatory concurrency (#450)
SOM requires mandatory concurrency to prevent hanging on 1-threaded configurations since this example has cross-graph dependencies

* SOM example: enable mandatory concurrency
* Add include & define NOMINMAX
* Improve comment wording

Signed-off-by: Kochin Ivan <kochin.ivan@intel.com>
Co-authored-by: Anton Potapov <anton.potapov@intel.com>
2021-06-22 09:38:19 +03:00
Ivan Kochin ac3d43b691 Enable intermodular optimization during the compilation (#432)
* Enable IPO during the compilation
* Add compilation flag for clang++
* Rework CMake approach
* Disable LTO on Android due to Android NDK bug
* Remove redundant code

Signed-off-by: Kochin, Ivan <kochin.ivan@intel.com>
2021-06-21 12:23:49 +03:00
vlserov fbc48b39c6 ASAN: Use after scope in conformance_concurrent_queue (#435)
Updating concurrent_queue_rep to accept Allocator as a function parameter instead of holding reference to it.

Signed-off-by: Serov, Vladimir <vladimir.serov@intel.com>
2021-06-18 10:21:25 +03:00
Sergey Zheltov 29009a8e51 Fix oneTBB package version in CMake integration (#446)
Signed-off-by: Zheltov, Sergey1 <sergey1.zheltov@intel.com>
2021-06-17 12:10:46 +03:00
Ilya Isaev 4beec37a1d Fix TSAN errors in collaborative_call_once (#445)
* Fix TSAN errors in collaborative_call_once

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>
2021-06-17 07:34:44 +03:00
Khem Raj 933a38a460 arena: Remove dead code (#429)
Fixes clang warning
arena.cpp:226:19: error: variable 'drained' set b
ut not used [-Werror,-Wunused-but-set-variable]
|     std::intptr_t drained = 0;
|                   ^

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2021-06-17 07:34:08 +03:00
Ilya Mishin 64715f43d8 Fix failed mips debug build (#443)
* Fix mips debug join_node tests

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>

* Macro in header

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>

* Macro name

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>

* Right macro

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>

* remove unnecessary macro

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>

* macro only in join_node test

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>
2021-06-16 12:09:09 +03:00
Alexandra 2526dcf136 Update README.md (#436)
* Update README.md
2021-06-10 15:05:29 +03:00
Ilya Mishin b36260b443 Enable all join_node constructors testing (#441)
* enable all constructors testing

Signed-off-by: Mishin, Ilya <ilya.mishin@intel.com>

* remove unnecessary definitions
2021-06-10 13:37:16 +03:00
vlserov 345a2204ca ASAN: skip test_malloc_atexit under ASAN (#434)
Skip test_malloc_atexit since it not applicable under ASAN.

Signed-off-by: Serov, Vladimir <vladimir.serov@intel.com>
2021-06-10 12:05:36 +03:00
Alex 81dd27c4f6 Fix some gcc11 warnings (#433)
* Supress mallinfo deprecation warning in test_malloc_overload.cpp
* Fix warning in flow_graph_types_impl

Signed-off-by: Alexei Katranov <alexei.katranov@intel.com>
2021-06-09 12:00:48 +03:00
Ivan Kochin 55f9b17864 Update doctest version to 2.4.6 (#413)
* Update doctest version to 2.4.6

Signed-off-by: Kochin, Ivan <kochin.ivan@intel.com>
2021-06-08 17:43:37 +03:00
PavelandAlexei Katranov 3119997522 Improve wakeup signal propagation in private server (#427)
* Improve wakeup signal propagation in private server

Signed-off-by: pkumbras <pavel.kumbrasev@intel.com>

Co-authored-by: Alexei Katranov <alexei.katranov@intel.com>
2021-06-07 16:51:19 +03:00
Rupanshu Yadav fc9a3bbc78 Fix grammatical mistake in README.md (#428) 2021-06-04 21:25:36 +03:00
Ilya MishinandAleksei Fedotov 25e2b1dd25 Fix negative delta in limiter_node decrementer (#422)
* fix negative delta in limiter_node decrementer

* add assert

* fix warning

* add new test

* refactor test

* more checks

Co-authored-by: Aleksei Fedotov <aleksei.fedotov@intel.com>

* counter to right place

* fix build

Co-authored-by: Aleksei Fedotov <aleksei.fedotov@intel.com>
2021-06-04 17:27:08 +03:00
vlserov 4b479c1e0b ASAN fix for test_malloc_regression (#415)
ASAN allocator never releases memory to OS, instead of it just marks those memory as "freed".
Generic OS functions for getting currently allocated memory aren't working correctly under ASAN.

- Using __sanitizer_get_current_allocated_bytes func instead of generic OS func for getting currently allocated memory

Signed-off-by: Serov, Vladimir <vladimir.serov@intel.com>
2021-06-02 16:55:58 +03:00
Ilya IsaevandAlex bf1f2ab6eb Add collaborative_call_once algorithm (#397)
collaborative_call_once is a function similar to std::call_once but allows waiting threads to join oneTBB parallel construction called inside the initializing functor. The semantics of exceptions is also similar to std::call_once: whenever the exception is thrown, it is rethrown on the initializing thread and this or other thread can try to call initializing functor again until it is completed without an exception.

This pull request integrates #357. It is reworked to avoid dynamic memory allocation and fit the state into one word (see state machine in #267).  In cooperation with @BenFrantzDale @HenryHeffanFormlabs

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>

Co-authored-by: Alex <alexei.katranov@intel.com>
2021-06-02 16:44:25 +03:00
Anton Potapov fde1856728 task_group extensions (task_handle) minor cleanups (#404)
- moved task_handle related stuff to separate header file
- replaced free standing helper functions with single "acessor" class
- removed needless condition in the ctx_of() function

Signed-off-by: Anton Potapov <anton.potapov@intel.com>
2021-06-01 15:34:30 +03:00
Anton Potapov 16350adcff ASAN: fix memory leak in concurrent_skip_list move assign operator (#409)
- delete head node as well beffore move assigning
 - introduced internal helper member function delete_head


Signed-off-by: Anton Potapov <anton.potapov@intel.com>
2021-05-31 18:11:34 +03:00
Ilya Isaev 012aea0351 Fix shellcheck scan errors and warnings (#411)
* Fix shellcheck errors and warnings

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>

* Apply comments and parse args properly on ZSH

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>

* Parse ia32 via regex

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>

* arg_ia32 to tbb_arg_ia32

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>

* Fix indenting

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>

* Change regex

Signed-off-by: Ilya Isaev <ilya.isaev@intel.com>
2021-05-26 20:20:51 +03:00
Ivan KochinandAlex c52c62ba78 Remove the same test cases to fix MIPS compilation (#412)
* Remove the same test cases to fix MIPS compilation

* Update test/tbb/test_join_node_msg_key_matching.cpp

Co-authored-by: Ivan Kochin <iv.kochin@gmail.com>

Co-authored-by: Alex <alexei.katranov@intel.com>
2021-05-25 14:33:00 +03:00
Alexei Katranov 3b04521726 Fix atomic usage in conformance_parallel_pipeline
Signed-off-by: Alexei Katranov <alexei.katranov@intel.com>
2021-05-25 08:02:10 +03:00
Jan Tojnar fa3268c3df CMake/pkg-config: fix paths in .pc file with absolute GNUInstallDirs (#395)
Signed-off-by: Jan Tojnar <jtojnar@gmail.com>
2021-05-21 18:46:06 +03:00
Ivan KochinandKochin, Ivan 5d4a4acf95 Fix the logic that depends on optional copy elision (#402)
* Fix the behavior when copy elision is disabled

* Update test/tbb/test_task_arena.cpp

* Rework doctest ContextScope destruction to fix MSVC compilation

* Remove raii_guard assignment + remove std::move from doctest

* Fix typo

* Rework the fix for doctest to get rid of hangs on Windows

* Add static assertion to check constructors noexcept state

* Remove copy elision disabling flag

* Add a comment with the reason of absence of std::move

Co-authored-by: Kochin, Ivan <ivan.kochin@intel.com>
2021-05-21 12:37:58 +03:00
Anton Potapov 0063fb3c76 ASAN fix for test_eh_algorithm (fixup for #401) (#403)
- fixup for #401

Signed-off-by: Anton Potapov <anton.potapov@intel.com>
2021-05-21 12:03:25 +03:00
Anton Potapov d8251013ce ASAN use after scope fix for concurrent_skip_list (#400)
- removed reference to container allocator from skip_list_node
 - added special skip_list_node::create skip_list_node::destroy static
methods

 - moved concurrent_skip_list, *_map/*multimap, *set/*multiset into d2
namespace due layout change of skip_list_node


Signed-off-by: Anton Potapov <anton.potapov@intel.com>
2021-05-21 10:50:08 +03:00
Anton Potapov 444fd2bd0f ASAN fix for test_eh_algorithm (#401)
- fixed read out of bounds

Signed-off-by: Anton Potapov <anton.potapov@intel.com>
2021-05-19 18:52:27 +03:00
Ilya Mishin 3e9e8c9c4d Add threshold requirement for eh tests (#399)
* Add threshold requirement for eeh tests

* typo error fix
2021-05-18 12:40:09 +03:00
Tobias Fischer c46e2aa03e Pull in https://github.com/oneapi-src/oneTBB/pull/299 2021-05-17 20:05:20 +03:00
Alexey Veprev a497817ca0 README: add CI status badge (#398)
Signed-off-by: Alexey Veprev <alexey.veprev@intel.com>
2021-05-17 14:39:38 +03:00
tbbdev 8b6f831c68 Commit oneTBB source code 5ba997e1 2021-05-17 10:52:00 +03:00
Sergey Zheltov 6aa706d879 CI: fix a typo in the job name (#392) 2021-05-07 21:24:55 +03:00
Sergey Zheltov 6caecf9630 CI: enable testing via GitHub Actions (#390) 2021-05-07 17:15:01 +03:00
tbbdev be66b3a1cf Commit oneTBB source code 614fdc20 2021-05-07 16:29:12 +03:00
tbbdev 478de5b188 Commit oneTBB source code 82ff8707 2021-05-05 10:28:54 +03:00
tbbdev 9e15720bc7 Commit oneTBB source code b0fb1535 2021-03-26 10:22:37 +03:00
tbbdev 4523a7615e Commit oneTBB source code 4fcd448a 2021-03-01 17:31:49 +03:00
tbbdev b15aabb39a Commit oneTBB source code 9ed4a21c 2021-01-26 15:10:57 +03:00
tbbdev d86ed7fbaa Commit oneTBB source code 09241505 2020-12-24 16:20:58 +03:00
tbbdev 8dcbd5b11b Commit oneTBB source code 8fda6294 2020-11-18 12:07:23 +03:00
tbbdev 49e08aac08 Commit oneTBB source code 6420d97a 2020-10-28 19:26:00 +03:00
tbbdev 51c0b2f742 Commit oneTBB source code 4ebd2d06 2020-09-25 11:03:12 +03:00
742 changed files with 250176 additions and 164 deletions
+45
View File
@@ -0,0 +1,45 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text
*.cpp text
*.def text
*.rc text
*.i text
*.sh text
*.csh text
*.mk text
*.java text
*.csv text
*.lst text
*.asm text
*.cfg text
*.css text
*.inc text
*.js text
*.rb text
*.strings text
*.txt text
*export.lst text
*.xml text
*.py text
*.md text
*.classpath text
*.cproject text
*.project text
*.properties text
*.java text
*.gradle text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
*.bat text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.ico binary
*.spir binary
+60
View File
@@ -0,0 +1,60 @@
#!/bin/bash
#
# Copyright (c) 2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
SCAN_TARGET=$1
SKIP_PATTERN='*/.github/*'
# Ignored cases
IGNORE_COMMAND="sed -e /.*\\sOd\\s*=.*/d \
-e /.*\\sOt\\s*=.*/d \
-e /.*\\siff\\s*=.*/d \
-e /.*\\sith\\s*=.*/d \
-e /.*\\scas\\s*=.*/d \
-e /.*\\sCAS\\s*=.*/d \
-e /.*\\ssom\\s*=.*/d \
-e /.*\\sSOM\\s*=.*/d \
-e /.*\\suint\\s*=.*/d \
-e /.*\\sUINT\\s*=.*/d \
-e /.*\\scopyable\\s*=.*/d \
-e /.*\\sCopyable\\s*=.*/d \
-e /.*\\sFo\\s*=.*/d \
-e /.*pipeline_filters.h.*nd\\s*=.*/d \
-e /.*ittnotify.h.*unx\\s*=.*/d \
-e /.*bzlib.cpp.*MSDOS\\s*=.*/d \
-e /.*test_task.cpp.*tE\\s*=.*/d \
-e /.*backend.cpp.*resSize\\s*=.*/d \
-e /.*test_join_node.h.*Ned\\s*=.*/d \
-e /.*test_indexer_node.cpp.*OT\\s*=.*/d \
-e /.*allocator_stl_test_common.h.*Aci*\\s*=.*/d \
-e /.*seismic_video.cpp.*DialogBox\\s*=.*/d \
-e /.*test_composite_node.cpp.*que\\s*=.*/d \
-e /.*blocksort.cpp.*hiSt\\s*=.*/d \
-e /.*compress.cpp.*fave\\s*=.*/d \
-e /.*count_strings.cpp.*ue\\s*=.*/d \
-e /.*count_strings.cpp.*nd\\s*=.*/d \
-e /.*count_strings.cpp.*ths\\s*=.*/d \
-e /.*polygon_overlay\/README.md.*ist\\s*=.*/d \
-e /.*_pipeline_filters.h.*nd\\s*=.*/d \
-e /.*sub_string_finder\/README.md.*ba\\s*=.*/d"
SCAN_RESULT=`codespell --quiet-level=2 --skip "${SKIP_PATTERN}" ${SCAN_TARGET}`
SCAN_RESULT=`echo -e "${SCAN_RESULT}" | ${IGNORE_COMMAND}`
echo "${SCAN_RESULT}"
if [[ ! -z ${SCAN_RESULT} ]]; then
exit 1
fi
+264
View File
@@ -0,0 +1,264 @@
# Copyright (c) 2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: oneTBB CI
on:
push:
branches: [master]
pull_request:
branches: [master]
types:
- opened
- synchronize
- reopened
env:
BUILD_CONCURRENCY: 2
MACOS_BUILD_CONCURRENCY: 3
TEST_TIMEOUT: 180
jobs:
codespell:
runs-on: [ubuntu-20.04]
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: Run scan
run: |
sudo apt update && sudo apt install -y codespell
${GITHUB_WORKSPACE}/.github/scripts/codespell.sh `pwd`
examples_clang-format:
runs-on: [ubuntu-20.04]
timeout-minutes: 10
steps:
- uses: actions/checkout@v2
- name: Run scan
run: |
cp -r examples examples_formatted
find examples_formatted -regex '.*\.\(cpp\|hpp\)' -exec clang-format-9 -style=file -i {} \;
diff -r examples examples_formatted
python_module_test_ubuntu18-04:
runs-on: [ubuntu-18.04]
timeout-minutes: 15
steps:
- uses: actions/checkout@v2
- name: Run testing
run: |
mkdir build && cd build
cmake -DTBB4PY_BUILD=ON -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc ..
make VERBOSE=1 -j${BUILD_CONCURRENCY} python_build
ctest -R python_test --output-on-failure --timeout ${TEST_TIMEOUT}
linux-testing:
name: ${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
runs-on: ['${{ matrix.os }}']
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
c_compiler: gcc
cxx_compiler: g++
std: 14
build_type: relwithdebinfo
preview: 'OFF'
- os: ubuntu-20.04
c_compiler: gcc
cxx_compiler: g++
std: 17
build_type: release
preview: 'ON'
- os: ubuntu-20.04
c_compiler: gcc-10
cxx_compiler: g++-10
std: 20
build_type: debug
preview: 'ON'
steps:
- uses: actions/checkout@v2
- name: Run testing
shell: bash
run: |
set -x
mkdir build && cd build
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} ..
make VERBOSE=1 -j${BUILD_CONCURRENCY}
ctest --timeout ${TEST_TIMEOUT} --output-on-failure
macos-testing:
name: ${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
runs-on: ['${{ matrix.os }}']
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- os: macos-10.15
c_compiler: clang
cxx_compiler: clang++
std: 14
build_type: relwithdebinfo
preview: 'ON'
steps:
- uses: actions/checkout@v2
- name: Run testing
shell: bash
run: |
set -x
mkdir build && cd build
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} ..
make VERBOSE=1 -j${MACOS_BUILD_CONCURRENCY}
ctest --timeout ${TEST_TIMEOUT} --output-on-failure
windows-testing:
name: ${{ matrix.job_name }}
runs-on: ['${{ matrix.os }}']
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- os: windows-2016
generator: Visual Studio 15 2017
c_compiler: cl
cxx_compiler: cl
std: 14
build_type: relwithdebinfo
preview: 'ON'
job_name: windows_cl2017_cxx14_relwithdebinfo_preview=ON
- os: windows-2019
generator: Visual Studio 16 2019
c_compiler: cl
cxx_compiler: cl
std: 17
build_type: relwithdebinfo
preview: 'OFF'
job_name: windows_cl2019_cxx17_relwithdebinfo_preview=OFF
steps:
- uses: actions/checkout@v2
- name: Run testing
run: |
mkdir build
cd build
cmake -G "${{ matrix.generator }}" -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.std }} `
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} `
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} ..
cmake --build . --config ${{ matrix.build_type }} -j -v
ctest -C ${{ matrix.build_type }} --timeout ${env:TEST_TIMEOUT} --output-on-failure
linux-examples-testing:
name: examples_${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
runs-on: ['${{ matrix.os }}']
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
c_compiler: gcc
cxx_compiler: g++
std: 14
build_type: relwithdebinfo
preview: 'OFF'
- os: ubuntu-20.04
c_compiler: gcc
cxx_compiler: g++
std: 17
build_type: release
preview: 'ON'
- os: ubuntu-20.04
c_compiler: gcc-10
cxx_compiler: g++-10
std: 20
build_type: debug
preview: 'ON'
steps:
- uses: actions/checkout@v2
- name: Run testing
shell: bash
run: |
set -x
mkdir build && cd build
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \
-DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
cmake --build . -v --target light_test_examples
macos-examples-testing:
name: examples_${{ matrix.os }}_${{ matrix.cxx_compiler }}_cxx${{ matrix.std }}_${{ matrix.build_type }}_preview=${{ matrix.preview }}
runs-on: ['${{ matrix.os }}']
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- os: macos-10.15
c_compiler: clang
cxx_compiler: clang++
std: 14
build_type: relwithdebinfo
preview: 'ON'
steps:
- uses: actions/checkout@v2
- name: Run testing
shell: bash
run: |
set -x
mkdir build && cd build
cmake -DCMAKE_CXX_STANDARD=${{ matrix.std }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \
-DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
cmake --build . -v --target light_test_examples
windows-examples-testing:
name: ${{ matrix.job_name }}
runs-on: ['${{ matrix.os }}']
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- os: windows-2016
generator: Visual Studio 15 2017
c_compiler: cl
cxx_compiler: cl
std: 14
build_type: relwithdebinfo
preview: 'ON'
job_name: examples_windows_cl2017_cxx14_relwithdebinfo_preview=ON
- os: windows-2019
generator: Visual Studio 16 2019
c_compiler: cl
cxx_compiler: cl
std: 17
build_type: relwithdebinfo
preview: 'OFF'
job_name: examples_windows_cl2019_cxx17_relwithdebinfo_preview=OFF
steps:
- uses: actions/checkout@v2
- name: Run testing
run: |
mkdir build
cd build
cmake -G "${{ matrix.generator }}" -A x64 -DCMAKE_CXX_STANDARD=${{ matrix.std }} `
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cxx_compiler }} `
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DTBB_CPF=${{ matrix.preview }} -DTBB_TEST=OFF -DTBB_EXAMPLES=ON ..
cmake --build . -v --target light_test_examples
+62
View File
@@ -0,0 +1,62 @@
# -------- C++ --------
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# -------- CMake --------
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
build/*
# -------- Python --------
__pycache__/
*.py[cod]
*$py.class
# -------- IDE --------
.vscode/*
.vs/*
out/*
CMakeSettings.json
# -------- CTags --------
.tags
.ctags
+270
View File
@@ -0,0 +1,270 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
# Enable CMake policies
if (POLICY CMP0091)
# The NEW behavior for this policy is to not place MSVC runtime library flags in the default
# CMAKE_<LANG>_FLAGS_<CONFIG> cache entries and use CMAKE_MSVC_RUNTIME_LIBRARY abstraction instead.
cmake_policy(SET CMP0091 NEW)
elseif (DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
message(FATAL_ERROR "CMAKE_MSVC_RUNTIME_LIBRARY was defined while policy CMP0091 is not available. Use CMake 3.15 or newer.")
endif()
if (TBB_WINDOWS_DRIVER AND (NOT ("${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL MultiThreaded OR "${CMAKE_MSVC_RUNTIME_LIBRARY}" STREQUAL MultiThreadedDebug)))
message(FATAL_ERROR "Enabled TBB_WINDOWS_DRIVER requires CMAKE_MSVC_RUNTIME_LIBRARY to be set to MultiThreaded or MultiThreadedDebug.")
endif()
# Enable support of minimum supported macOS version flag
if (APPLE)
if (NOT CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG)
set(CMAKE_CXX_OSX_DEPLOYMENT_TARGET_FLAG "-mmacosx-version-min=" CACHE STRING "Minimum macOS version flag")
endif()
if (NOT CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG)
set(CMAKE_C_OSX_DEPLOYMENT_TARGET_FLAG "-mmacosx-version-min=" CACHE STRING "Minimum macOS version flag")
endif()
endif()
# Until CMake 3.4.0 FindThreads.cmake requires C language enabled.
# Enable C language before CXX to avoid possible override of CMAKE_SIZEOF_VOID_P.
if (CMAKE_VERSION VERSION_LESS 3.4)
enable_language(C)
endif()
file(READ include/oneapi/tbb/version.h _tbb_version_info)
string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" _tbb_ver_major "${_tbb_version_info}")
string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" _tbb_ver_minor "${_tbb_version_info}")
string(REGEX REPLACE ".*#define TBB_VERSION_PATCH ([0-9]+).*" "\\1" _tbb_ver_patch "${_tbb_version_info}")
string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_tbb_version_info}")
string(REGEX REPLACE ".*#define __TBB_BINARY_VERSION ([0-9]+).*" "\\1" TBB_BINARY_VERSION "${_tbb_version_info}")
set(TBB_BINARY_MINOR_VERSION ${_tbb_ver_minor})
set(TBBMALLOC_BINARY_VERSION 2)
set(TBBBIND_BINARY_VERSION 3)
project(TBB VERSION ${_tbb_ver_major}.${_tbb_ver_minor}.${_tbb_ver_patch} LANGUAGES CXX)
unset(_tbb_ver_major)
unset(_tbb_ver_minor)
include(CheckCXXCompilerFlag)
include(GNUInstallDirs)
# ---------------------------------------------------------------------------------------------------------
# Handle C++ standard version.
if (NOT MSVC) # no need to cover MSVC as it uses C++14 by default.
if (NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
if (CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION) # if standard option was detected by CMake
set(CMAKE_CXX_STANDARD_REQUIRED ON)
else() # if standard option wasn't detected by CMake (e.g. for Intel Compiler with CMake 3.1)
# TBB_CXX_STD_FLAG should be added to targets via target_compile_options
set(TBB_CXX_STD_FLAG -std=c++${CMAKE_CXX_STANDARD})
check_cxx_compiler_flag(${TBB_CXX_STD_FLAG} c++${CMAKE_CXX_STANDARD})
if (NOT c++${CMAKE_CXX_STANDARD})
message(FATAL_ERROR "C++${CMAKE_CXX_STANDARD} (${TBB_CXX_STD_FLAG}) support is required")
endif()
unset(c++${CMAKE_CXX_STANDARD})
endif()
endif()
set(CMAKE_CXX_EXTENSIONS OFF) # use -std=c++... instead of -std=gnu++...
# ---------------------------------------------------------------------------------------------------------
# Detect architecture (bitness).
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set(TBB_ARCH 32)
else()
set(TBB_ARCH 64)
endif()
option(TBB_TEST "Enable testing" ON)
option(TBB_EXAMPLES "Enable examples" OFF)
option(TBB_STRICT "Treat compiler warnings as errors" ON)
option(TBB_WINDOWS_DRIVER "Build as Universal Windows Driver (UWD)" OFF)
option(TBB_NO_APPCONTAINER "Apply /APPCONTAINER:NO (for testing binaries for Windows Store)" OFF)
option(TBB4PY_BUILD "Enable tbb4py build" OFF)
option(TBB_CPF "Enable preview features of the library" OFF)
option(TBB_FIND_PACKAGE "Enable search for external oneTBB using find_package instead of build from sources" OFF)
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif()
if (NOT BUILD_SHARED_LIBS)
message(WARNING "You are building oneTBB as a static library. This is highly discouraged and such configuration is not supported. Consider building a dynamic library to avoid unforeseen issues.")
endif()
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Build type" FORCE)
message(STATUS "CMAKE_BUILD_TYPE is not specified. Using default: ${CMAKE_BUILD_TYPE}")
# Possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# -------------------------------------------------------------------
# Files and folders naming
set(CMAKE_DEBUG_POSTFIX _debug)
if (NOT DEFINED TBB_OUTPUT_DIR_BASE)
if (MSVC)
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES DLL)
set(_tbb_msvc_runtime _md)
else()
set(_tbb_msvc_runtime _mt)
endif()
if (WINDOWS_STORE)
if (TBB_NO_APPCONTAINER)
set(_tbb_win_store _wsnoappcont)
else()
set(_tbb_win_store _ws)
endif()
elseif(TBB_WINDOWS_DRIVER)
set(_tbb_win_store _wd)
endif()
endif()
string(REGEX MATCH "^([0-9]+\.[0-9]+|[0-9]+)" _tbb_compiler_version_short ${CMAKE_CXX_COMPILER_VERSION})
string(TOLOWER ${CMAKE_CXX_COMPILER_ID}_${_tbb_compiler_version_short}_cxx${CMAKE_CXX_STANDARD}_${TBB_ARCH}${_tbb_msvc_runtime}${_tbb_win_store} TBB_OUTPUT_DIR_BASE)
unset(_tbb_msvc_runtime)
unset(_tbb_win_store)
unset(_tbb_compiler_version_short)
endif()
foreach(output_type LIBRARY ARCHIVE PDB RUNTIME)
if (CMAKE_BUILD_TYPE)
string(TOLOWER ${CMAKE_BUILD_TYPE} _tbb_build_type_lower)
set(CMAKE_${output_type}_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${TBB_OUTPUT_DIR_BASE}_${_tbb_build_type_lower})
unset(_tbb_build_type_lower)
endif()
if (CMAKE_CONFIGURATION_TYPES)
foreach(suffix ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${suffix} _tbb_suffix_upper)
string(TOLOWER ${suffix} _tbb_suffix_lower)
set(CMAKE_${output_type}_OUTPUT_DIRECTORY_${_tbb_suffix_upper} ${CMAKE_BINARY_DIR}/${TBB_OUTPUT_DIR_BASE}_${_tbb_suffix_lower})
endforeach()
unset(_tbb_suffix_lower)
unset(_tbb_suffix_upper)
endif()
endforeach()
# -------------------------------------------------------------------
# -------------------------------------------------------------------
# Common dependencies
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package(Threads REQUIRED)
# -------------------------------------------------------------------
file(GLOB FILES_WITH_EXTRA_TARGETS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/*.cmake)
foreach(FILE_WITH_EXTRA_TARGETS ${FILES_WITH_EXTRA_TARGETS})
include(${FILE_WITH_EXTRA_TARGETS})
endforeach()
set(TBB_COMPILER_SETTINGS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compilers/${CMAKE_CXX_COMPILER_ID}.cmake)
if (EXISTS ${TBB_COMPILER_SETTINGS_FILE})
include(${TBB_COMPILER_SETTINGS_FILE})
else()
message(WARNING "TBB compiler settings not found ${TBB_COMPILER_SETTINGS_FILE}")
endif()
if (TBB_FIND_PACKAGE OR TBB_DIR)
# Allow specifying external TBB to test with.
# Do not add main targets and installation instructions in that case.
message(STATUS "Using external TBB for testing")
find_package(TBB REQUIRED)
else()
add_subdirectory(src/tbb)
if (NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
add_subdirectory(src/tbbmalloc)
add_subdirectory(src/tbbmalloc_proxy)
if (APPLE)
message(STATUS "TBBBind build target is disabled due to unsupported environment")
else()
add_subdirectory(src/tbbbind)
endif()
endif()
# -------------------------------------------------------------------
# Installation instructions
include(CMakePackageConfigHelpers)
install(DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
COMPONENT devel)
install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE TBB::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
COMPONENT devel)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
"include(\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}Targets.cmake)\n")
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
COMPATIBILITY AnyNewerVersion)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
COMPONENT devel)
install(FILES "README.md"
DESTINATION ${CMAKE_INSTALL_DOCDIR}
COMPONENT devel)
# -------------------------------------------------------------------
endif()
if (TBB_TEST)
enable_testing()
add_subdirectory(test)
endif()
if (TBB_EXAMPLES)
add_subdirectory(examples)
endif()
if (TBB_BENCH)
if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/benchmark)
message(FATAL_ERROR "Benchmarks are not supported yet")
endif()
enable_testing()
add_subdirectory(benchmark)
endif()
if (ANDROID_PLATFORM)
if (${ANDROID_STL} STREQUAL "c++_shared")
configure_file(
"${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libc++_shared.so"
"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libc++_shared.so"
COPYONLY)
endif()
# This custom target may be implemented without separate CMake script, but it requires
# ADB(Android Debug Bridge) executable file availability, so to incapsulate this requirement
# only for corresponding custom target, it was implemented by this way.
add_custom_target(device_environment_cleanup COMMAND ${CMAKE_COMMAND}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/device_environment_cleanup.cmake)
endif()
if (TBB4PY_BUILD)
add_subdirectory(python)
endif()
# Keep it the last instruction.
add_subdirectory(cmake/post_install)
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+37 -19
View File
@@ -1,30 +1,48 @@
# Intel(R) Threading Building Blocks
# oneAPI Threading Building Blocks
[![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE.txt) [![oneTBB CI](https://github.com/oneapi-src/oneTBB/actions/workflows/ci.yml/badge.svg)](https://github.com/oneapi-src/oneTBB/actions/workflows/ci.yml?query=branch%3Amaster)
Intel(R) Threading Building Blocks (Intel(R) TBB) lets you easily write parallel C++ programs that take
oneAPI Threading Building Blocks (oneTBB) lets you easily write parallel C++ programs that take
full advantage of multicore performance, that are portable, composable and have future-proof scalability.
## Intel(R) TBB Distribution
* Commercial version: [https://software.intel.com/en-us/intel-tbb](https://software.intel.com/en-us/intel-tbb)
* Community licensing: [https://software.intel.com/sites/campaigns/nest/](https://software.intel.com/sites/campaigns/nest/)
* Open source version: [https://www.threadingbuildingblocks.org/](https://www.threadingbuildingblocks.org/)
* Intel(R) TBB for Python\*: [http://anaconda.org/intel/tbb](http://anaconda.org/intel/tbb)
## Release Information
Here are [Release Notes]( https://software.intel.com/en-us/articles/intel-oneapi-threading-building-blocks-release-notes) and
[System Requirements](https://software.intel.com/en-us/articles/intel-oneapi-threading-building-blocks-system-requirements).
## Repository Content
This is an official Intel(R) TBB public GitHub repository. All source and binary packages starting from Intel(R) TBB 4.4
can be found at the [Release page](https://github.com/01org/tbb/releases). Links to the packages with older versions of
Intel(R) TBB can be found in the [download.md](download.md) file.
## Documentation
* [oneTBB Specification](https://spec.oneapi.com/versions/latest/elements/oneTBB/source/nested-index.html)
* [oneTBB Developer Guide and Reference](https://software.intel.com/en-us/oneapi-tbb-documentation)
* [Migrating from TBB to oneTBB](https://software.intel.com/content/www/us/en/develop/documentation/onetbb-documentation/top/onetbb-developer-guide/migrating-from-threading-building-blocks-tbb.html)
* README for build system: [cmake/README.md](cmake/README.md)
## Repository Structure
The Master branch is empty and contains only README.md and download.md files.
## Support
Please report issues and suggestions via
[GitHub issues](https://github.com/oneapi-src/oneTBB/issues) or start a topic on the
[oneTBB forum](https://community.intel.com/t5/Intel-oneAPI-Threading-Building/bd-p/oneapi-threading-building-blocks).
tbb_\<major_version\> - branch for the new major version. All minor versions of the major release will be committed in this branch.
## How to Contribute
To contribute to oneTBB, please open a GitHub pull request (preferred) or send us a patch by e-mail.
For example:
* Intel(R) TBB 2017 initial release goes to branch tbb_2017.
* Intel(R) TBB 2017 Update 1 will go to branch tbb_2017 too.
* Intel(R) TBB 2018 initial release will go to branch tbb_2018.
Please use the sign-off line at the end of the patch.
Your signature certifies that you wrote the patch or
otherwise have the right to pass it on as an open-source patch.
The rules are pretty simple:
if you can certify the https://developercertificate.org then you just add a line to every git commit message:
```
Signed-off-by: Name Surname <user@email.com>
```
Use your real name (sorry, no pseudonyms or anonymous contributions).
## Сontact engineering team
If you set your `user.name` and `user.email` git configs, you can sign your
commit automatically with `git commit -s`.
## License
oneAPI Threading Building Blocks is licensed under [Apache License, Version 2.0](LICENSE.txt).
By its terms, contributions submitted to the project are also done under that license.
## Security
To report security issues please go to https://intel.com/security.
## Engineering team contacts
* [E-mail us.](mailto:inteltbbdevelopers@intel.com)
------------------------------------------------------------------------
+284
View File
@@ -0,0 +1,284 @@
# Build system description
The project uses CMake build configuration.
The following controls are available during the configure stage:
```
TBB_TEST:BOOL - Enable testing (ON by default)
TBB_STRICT:BOOL - Treat compiler warnings as errors (ON by default)
TBB_SANITIZE:STRING - Sanitizer parameter, passed to compiler/linker
TBB_SIGNTOOL:FILEPATH - Tool for digital signing, used in post install step for libraries if provided.
TBB_SIGNTOOL_ARGS:STRING - Additional arguments for TBB_SIGNTOOL, used if TBB_SIGNTOOL is set.
TBB4PY_BUILD:BOOL - Enable Intel(R) oneAPI Threading Building Blocks (oneTBB) Python module build (OFF by default)
TBB_CPF:BOOL - Enable preview features of the library (OFF by default)
TBB_INSTALL_VARS:BOOL - Enable auto-generated vars installation(packages generated by `cpack` and `make install` will also include the vars script)(OFF by default)
TBB_VALGRIND_MEMCHECK:BOOL - Enable scan for memory leaks using Valgrind (OFF by default)
```
## Configure, build and test
### Prerequisites
* CMake >= 3.1
### Preparation
In order to perform out-of-source build you have to create a build directory and go there:
```bash
mkdir /tmp/my-build
cd /tmp/my-build
```
### Configure
```bash
cmake <options> <repo_root>
```
Some useful options:
- `-G <generator>` - specify particular project generator, see `cmake --help` for details.
- `-DCMAKE_BUILD_TYPE=Debug` - specify for Debug build, it isn't applicable for multi-config generators, e.g. for Visual Studio generator).
#### TBBBind library configuration
The TBBbind library has two versions: `tbbbind` and `tbbbind_2_0`. Each of these versions is linked with corresponding HWLOC library version: `tbbbind` links with HWLOC 1.11.x , `tbbbind_2_0` links with HWLOC 2.x.
To enable the TBBBind library build or special tests that performed inside the HWLOC environment, please specify the following CMake variables:
- `CMAKE_HWLOC_<HWLOC_VER>_LIBRARY_PATH` - path to the corresponding HWLOC version shared library on Linux or path to `.lib` file on Windows.
- `CMAKE_HWLOC_<HWLOC_VER>_INCLUDE_PATH` - path to the corresponding HWLOC version includes directory.
Windows requires one additional variable for correct TBBBind library building:
- `CMAKE_HWLOC_<HWLOC_VER>_DLL_PATH` - path to the corresponding HWLOC version `.dll` file.
`HWLOC_VER` variable used above can be replaced with one of the two values: `1_11` for the `tbbbind` library configuration and `2` for the `tbbbind_2_0` library configuration.
### Build
```bash
cmake --build . <options>
```
Some useful options:
- `--target <target>` - specific target, "all" is default.
- `--config <Release|Debug>` - build configuration, applicable only for multi-config generators, e.g. Visual Studio generator.
Binaries are placed to `./<compiler-id>_<compiler-ver>_cxx<stdver>_<build-type>` (for example, `./gnu_4.8_cxx11_release`)
#### Build for 32-bit
* Intel Compiler: just source Intel(R) C++ Compiler with `ia32` and build as usual.
* MSVC: use switch for [generator](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) (e.g. `-A Win32` for [VS2019](https://cmake.org/cmake/help/latest/generator/Visual%20Studio%2016%202019.html)) during the configuration stage and then build as usual.
* GCC/Clang: specify `-m32` during the configuration: `CXXFLAGS=-m32 cmake ..` or `cmake -DCMAKE_CXX_FLAGS=-m32 ..`
* Any other compiler which builds for 64-bit by default: specify 32-bit compiler key during the configuration as above.
#### Windows specific builds (CMake 3.15 or newer is required)
* Dynamic linkage with CRT: default behavior, can be explicitly specified by setting `CMAKE_MSVC_RUNTIME_LIBRARY` to `MultiThreadedDLL` or `MultiThreadedDebugDLL`.
```bash
cmake .. # dynamic linkage is used by default
```
```bash
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ..
```
```bash
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebugDLL -DCMAKE_BUILD_TYPE=Debug ..
```
* Static linkage with CRT: set `CMAKE_MSVC_RUNTIME_LIBRARY` to `MultiThreaded` or `MultiThreadedDebug`.
```bash
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ..
```
```bash
cmake -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug -DCMAKE_BUILD_TYPE=Debug ..
```
* Windows 10 Universal Windows application build: set `CMAKE_SYSTEM_NAME` to `WindowsStore` and `CMAKE_SYSTEM_VERSION` to `10.0`.
_Note: set `TBB_NO_APPCONTAINER` to `ON` in order to apply `/APPCONTAINER:NO` option during the compilation (used for testing)._
```bash
cmake -DCMAKE_SYSTEM_NAME:STRING=WindowsStore -DCMAKE_SYSTEM_VERSION:STRING=10.0 ..
```
* Universal Windows Driver build: set `TBB_WINDOWS_DRIVER` to `ON` and use static linkage with CRT (see above).
```bash
cmake -DTBB_WINDOWS_DRIVER=ON -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ..
```
### Test
#### Build test
Using default ('all') target:
```
cmake --build .
```
or using specific test target:
```
cmake --build . --target <test> # e.g. test_version
```
#### Run test
Using CTest:
```bash
ctest
```
or using 'test' target:
```bash
cmake --build . --target test # currently doesn't work on Windows
```
## Sanitizers - сonfigure, build and run
```bash
mkdir build
cd build
cmake -DTBB_SANITIZE=thread .. # or -DTBB_SANITIZE=memory or any other sanitizer
make -j
ctest -V
```
## Valgrind memcheck - configure, build and run
### Prerequisites
* Valgrind tool executable
### Example
```bash
mkdir build
cd build
cmake -DTBB_VALGRIND_MEMCHECK=ON ..
make -j memcheck-<test name> # or memcheck-all to scan all tests
```
## Test specification (Doxygen)
```bash
mkdir build
cd build
cmake -DTBB_TEST_SPEC=ON ..
make test_spec
```
## Intallation and packaging
**NOTE: be careful about installation: avoid commands like `make install` unless you fully understand the consequences.**
The following install components are supported:
- `runtime` - oneTBB runtime package (core shared libraries and `.dll` files on Windows).
- `devel` - oneTBB development package (header files, CMake integration files, library symbolic links and `.lib` files on Windows).
- `tbb4py` - [oneTBB Module for Python](#onetbb-python-module-support).
How to install specific components after configuration and build:
```bash
cmake -DCOMPONENT=<component> [-DBUILD_TYPE=<build-type>] -P cmake_install.cmake
```
Simple packaging using CPack is supported.
The following commands allow to create a simple portable package which includes header files, libraries and integration files for CMake:
```bash
cmake <options> ..
cpack
```
## TBBConfig - integration of binary packages
It is a configuration module that is used for integration of prebuilt oneTBB. It consists of two files (TBBConfig.cmake and TBBConfigVersion.cmake) and can be used via [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) function.
How to use this module in your CMake project:
1. Let CMake know where to search for TBBConfig, e.g. specify location of TBBConfig.cmake in `TBB_DIR` (for more details about search paths see [find_package](https://cmake.org/cmake/help/latest/command/find_package.html)).
2. Use [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) to find oneTBB.
3. Use provided variables and/or imported targets (described below) to work with the found oneTBB.
Example:
```cmake
add_executable(foo foo.cpp)
find_package(TBB)
target_link_libraries(foo TBB::tbb)
```
oneTBB components can be passed to [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) after keyword ``COMPONENTS`` or ``REQUIRED``.
Use basic names of components (`tbb`, `tbbmalloc`, etc.).
If components are not specified then the default set is used: `tbb`, `tbbmalloc` and ``tbbmalloc_proxy``.
If `tbbmalloc_proxy` is requested, `tbbmalloc` component will also be added and set as dependency for `tbbmalloc_proxy`.
TBBConfig creates [imported targets](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#imported-targets>) as
shared libraries using the following format: `TBB::<component>` (for example, `TBB::tbb`, `TBB::tbbmalloc`).
Set `TBB_FIND_RELEASE_ONLY` to `TRUE` before calling `find_package` in order to search only for release oneTBB version. This variable helps to avoid simultaneous linkage of release and debug oneTBB versions when CMake configuration is `Debug` but a third-party component depends on release oneTBB version.
Variables set during TBB configuration:
Variable | Description
--- | ---
`TBB_FOUND` | oneTBB is found
`TBB_<component>_FOUND` | Specific oneTBB component is found
`TBB_VERSION` | oneTBB version (format: `<major>.<minor>.<patch>.<tweak>`)
`TBB_IMPORTED_TARGETS` | All created oneTBB imported targets (not supported for builds from source code)
Starting from [oneTBB 2021.1](https://github.com/oneapi-src/oneTBB/releases/tag/v2021.1) GitHub release TBBConfig files in the binary packages are located under `<tbb-root>/lib/cmake/TBB`.
For example, `TBB_DIR` should be set to `<tbb-root>/lib/cmake/TBB`.
TBBConfig files are automatically created during the build from source code and can be installed together with the library.
Also oneTBB provides a helper function that creates TBBConfig files from predefined templates: see `tbb_generate_config` in `cmake/config_generation.cmake`.
## oneTBB Python Module support
`TBB4PY_BUILD` Cmake option provides ability to build Python module for oneTBB.
### Targets:
- `irml` - build IPC RML server
- `python_build` - build oneTBB module for Python
`python_build` target requirements:
- Python version 3.5 or newer
- SWIG version 3.0.6 or newer
## CMake files
### Compile/link options
Compile and link options may be specific for certain compilers. This part is handled in `cmake/compilers/*` files.
Options in TBB CMake are handled via variables in two ways for convenience:
* by options group
* by specific option
#### Options group
Naming convention is the following: `TBB_<SCOPE>_<STAGE>_<CATEGORY>`, where
* `<SCOPE>` could be
* `LIB` - options applied during libraries build.
* `TEST` - options applied during test build.
* `BENCH` - options applied during benchmarks build.
* `COMMON` - options applied during all (libraries, test, benchmarks) builds.
* `<STAGE>` could be
* `COMPILE` - options applied during the compilation.
* `LINK` - options applied during the linkage.
* `<CATEGORY>` could be
* `FLAGS` - list of flags
* `LIBS` - list of libraries
*Examples*
Variable | Description
--- | ---
`TBB_COMMON_COMPILE_FLAGS` | Applied to libraries, tests and benchmarks as compile options
`TBB_LIB_LINK_FLAGS` | Applied to libraries as link options
`TBB_LIB_LINK_LIBS ` | Applied to libraries as link libraries
`TBB_TEST_COMPILE_FLAGS` | Applied to tests as compile options
#### Specific options
If the option used only in part of the places (library, tests, benchmarks) as well as adding this option to the group of other options is not possible,
then the option must be named using common sense.
Warnings supperssions should be added into `TBB_WARNING_SUPPRESS` variable which is applied during the compilation of libraries, tests and benchmarks.
Additional warnings should be added into `TBB_WARNING_TEST_FLAGS` variable which is applied during the compilation of tests.
@@ -0,0 +1,17 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(${CMAKE_CURRENT_LIST_DIR}/environment.cmake)
execute_on_device("rm -rf ${ANDROID_DEVICE_TESTING_DIRECTORY}")
+35
View File
@@ -0,0 +1,35 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(ANDROID_DEVICE_TESTING_DIRECTORY "/data/local/tmp/tbb_testing")
find_program(adb_executable adb)
if (NOT adb_executable)
message(FATAL_ERROR "Could not find adb")
endif()
macro(execute_on_device cmd)
execute_process(COMMAND ${adb_executable} shell ${cmd} RESULT_VARIABLE CMD_RESULT)
if (CMD_RESULT)
message(FATAL_ERROR "Error while on device execution: ${cmd} error_code: ${CMD_RESULT}")
endif()
endmacro()
macro(transfer_data data_path)
execute_process(COMMAND ${adb_executable} push --sync ${data_path} ${ANDROID_DEVICE_TESTING_DIRECTORY}
RESULT_VARIABLE CMD_RESULT OUTPUT_QUIET)
if (CMD_RESULT)
message(FATAL_ERROR "Error while data transferring: ${data_path} error_code: ${CMD_RESULT}")
endif()
endmacro()
+27
View File
@@ -0,0 +1,27 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(${CMAKE_CURRENT_LIST_DIR}/environment.cmake)
# transfer data to device
execute_on_device("mkdir -m 755 -p ${ANDROID_DEVICE_TESTING_DIRECTORY}")
file (GLOB_RECURSE BINARIES_LIST "${BINARIES_PATH}/*.so*" "${BINARIES_PATH}/${TEST_NAME}")
foreach(BINARY_FILE ${BINARIES_LIST})
transfer_data(${BINARY_FILE})
endforeach()
# execute binary
execute_on_device("chmod -R 755 ${ANDROID_DEVICE_TESTING_DIRECTORY}")
execute_on_device("LD_LIBRARY_PATH=${ANDROID_DEVICE_TESTING_DIRECTORY} ${ANDROID_DEVICE_TESTING_DIRECTORY}/${TEST_NAME}")
+41
View File
@@ -0,0 +1,41 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(TBB_LINK_DEF_FILE_FLAG -Wl,-exported_symbols_list,)
set(TBB_DEF_FILE_PREFIX mac${TBB_ARCH})
set(TBB_WARNING_LEVEL -Wall -Wextra $<$<BOOL:${TBB_STRICT}>:-Werror>)
set(TBB_TEST_WARNING_FLAGS -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor)
set(TBB_WARNING_SUPPRESS -Wno-parentheses -Wno-non-virtual-dtor -Wno-dangling-else)
# For correct ucontext.h structures layout
set(TBB_COMMON_COMPILE_FLAGS -D_XOPEN_SOURCE)
# Depfile options (e.g. -MD) are inserted automatically in some cases.
# Don't add -MMD to avoid conflicts in such cases.
if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
set(TBB_MMD_FLAG -MMD)
endif()
# Ignore -Werror set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
tbb_remove_compile_flag(-Werror)
endif()
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) on relevant processors
if (NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES "^arm64$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|AMD64)") # OSX systems are 64-bit only
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm)
endif()
# TBB malloc settings
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
+59
View File
@@ -0,0 +1,59 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if (APPLE)
set(TBB_LINK_DEF_FILE_FLAG -Wl,-exported_symbols_list,)
set(TBB_DEF_FILE_PREFIX mac${TBB_ARCH})
# For correct ucontext.h structures layout
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -D_XOPEN_SOURCE)
else()
set(TBB_LINK_DEF_FILE_FLAG -Wl,--version-script=)
set(TBB_DEF_FILE_PREFIX lin${TBB_ARCH})
endif()
# Depfile options (e.g. -MD) are inserted automatically in some cases.
# Don't add -MMD to avoid conflicts in such cases.
if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
set(TBB_MMD_FLAG -MMD)
endif()
set(TBB_WARNING_LEVEL -Wall -Wextra $<$<BOOL:${TBB_STRICT}>:-Werror>)
set(TBB_TEST_WARNING_FLAGS -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor)
# Ignore -Werror set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
tbb_remove_compile_flag(-Werror)
endif()
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},12.0>>:-mwaitpkg>)
endif()
set(TBB_COMMON_LINK_LIBS dl)
if (ANDROID_PLATFORM)
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} $<$<NOT:$<CONFIG:Debug>>:-D_FORTIFY_SOURCE=2>)
endif()
# Enabling LTO on Android causes the NDK bug.
# NDK throws the warning: "argument unused during compilation: '-Wa,--noexecstack'"
if (NOT ANDROID_PLATFORM)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
endif()
# TBB malloc settings
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
+62
View File
@@ -0,0 +1,62 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if (APPLE)
set(TBB_LINK_DEF_FILE_FLAG -Wl,-exported_symbols_list,)
set(TBB_DEF_FILE_PREFIX mac${TBB_ARCH})
# For correct ucontext.h structures layout
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -D_XOPEN_SOURCE)
else()
set(TBB_LINK_DEF_FILE_FLAG -Wl,--version-script=)
set(TBB_DEF_FILE_PREFIX lin${TBB_ARCH})
endif()
set(TBB_WARNING_LEVEL -Wall -Wextra $<$<BOOL:${TBB_STRICT}>:-Werror> -Wfatal-errors)
set(TBB_TEST_WARNING_FLAGS -Wshadow -Wcast-qual -Woverloaded-virtual -Wnon-virtual-dtor)
# Depfile options (e.g. -MD) are inserted automatically in some cases.
# Don't add -MMD to avoid conflicts in such cases.
if (NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CXX_DEPENDS_USE_COMPILER)
set(TBB_MMD_FLAG -MMD)
endif()
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<AND:$<NOT:$<CXX_COMPILER_ID:Intel>>,$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},11.0>>>:-mwaitpkg>)
endif()
set(TBB_COMMON_LINK_LIBS dl)
# Ignore -Werror set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
tbb_remove_compile_flag(-Werror)
endif()
if (NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL Intel)
# gcc 6.0 and later have -flifetime-dse option that controls elimination of stores done outside the object lifetime
set(TBB_DSE_FLAG $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},6.0>>:-flifetime-dse=1>)
endif()
# Workaround for heavy tests and too many symbols in debug (rellocation truncated to fit: R_MIPS_CALL16)
if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips")
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} -DTBB_TEST_LOW_WORKLOAD $<$<CONFIG:DEBUG>:-mxgot>)
endif()
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:-flto>)
# TBB malloc settings
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
set(TBB_OPENMP_FLAG -fopenmp)
+36
View File
@@ -0,0 +1,36 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if (MSVC)
include(${CMAKE_CURRENT_LIST_DIR}/MSVC.cmake)
set(TBB_WARNING_LEVEL ${TBB_WARNING_LEVEL} /W3)
set(TBB_OPENMP_FLAG /Qopenmp)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/Qipo>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:/INCREMENTAL:NO>)
elseif (APPLE)
include(${CMAKE_CURRENT_LIST_DIR}/AppleClang.cmake)
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -fstack-protector -Wformat -Wformat-security
$<$<NOT:$<CONFIG:Debug>>:-fno-omit-frame-pointer -qno-opt-report-embed -D_FORTIFY_SOURCE=2>)
set(TBB_OPENMP_FLAG -qopenmp)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-ipo>)
else()
include(${CMAKE_CURRENT_LIST_DIR}/GNU.cmake)
set(TBB_LIB_LINK_FLAGS ${TBB_LIB_LINK_FLAGS} -static-intel -Wl,-z,relro,-z,now,)
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -fstack-protector -Wformat -Wformat-security
$<$<NOT:$<CONFIG:Debug>>:-qno-opt-report-embed -D_FORTIFY_SOURCE=2>
$<$<EQUAL:${TBB_ARCH},32>:-falign-stack=maintain-16-byte>)
set(TBB_OPENMP_FLAG -qopenmp)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-ipo>)
endif()
set(TBB_IPO_LINK_FLAGS ${TBB_IPO_LINK_FLAGS} ${TBB_IPO_COMPILE_FLAGS})
+27
View File
@@ -0,0 +1,27 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if (WIN32)
include(${CMAKE_CURRENT_LIST_DIR}/MSVC.cmake)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/Qipo>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:/INCREMENTAL:NO>)
else()
include(${CMAKE_CURRENT_LIST_DIR}/Clang.cmake)
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:-ipo>)
endif()
set(TBB_IPO_LINK_FLAGS ${TBB_IPO_LINK_FLAGS} ${TBB_IPO_COMPILE_FLAGS})
if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86|AMD64)")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm -mwaitpkg)
endif()
+75
View File
@@ -0,0 +1,75 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(TBB_LINK_DEF_FILE_FLAG ${CMAKE_LINK_DEF_FILE_FLAG})
set(TBB_DEF_FILE_PREFIX win${TBB_ARCH})
# Workaround for CMake issue https://gitlab.kitware.com/cmake/cmake/issues/18317.
# TODO: consider use of CMP0092 CMake policy.
string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# Warning suppression C4324: structure was padded due to alignment specifier
set(TBB_WARNING_LEVEL $<$<NOT:$<CXX_COMPILER_ID:Intel>>:/W4> $<$<BOOL:${TBB_STRICT}>:/WX>)
set(TBB_WARNING_SUPPRESS /wd4324)
set(TBB_TEST_COMPILE_FLAGS /bigobj)
if (MSVC_VERSION LESS_EQUAL 1900)
# Warning suppression C4503 for VS2015 and earlier:
# decorated name length exceeded, name was truncated.
# More info can be found at
# https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4503
set(TBB_TEST_COMPILE_FLAGS ${TBB_TEST_COMPILE_FLAGS} /wd4503)
endif()
set(TBB_LIB_COMPILE_FLAGS -D_CRT_SECURE_NO_WARNINGS /GS)
set(TBB_COMMON_COMPILE_FLAGS /volatile:iso /FS)
# Ignore /WX set through add_compile_options() or added to CMAKE_CXX_FLAGS if TBB_STRICT is disabled.
if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
tbb_remove_compile_flag(/WX)
endif()
if (WINDOWS_STORE OR TBB_WINDOWS_DRIVER)
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} /D_WIN32_WINNT=0x0A00)
set(TBB_COMMON_LINK_FLAGS /NODEFAULTLIB:kernel32.lib /INCREMENTAL:NO)
set(TBB_COMMON_LINK_LIBS OneCore.lib)
endif()
if (WINDOWS_STORE)
if (NOT CMAKE_SYSTEM_VERSION EQUAL 10.0)
message(FATAL_ERROR "CMAKE_SYSTEM_VERSION must be equal to 10.0")
endif()
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} /ZW /ZW:nostdlib)
# CMake define this extra lib, remove it for this build type
string(REGEX REPLACE "WindowsApp.lib" "" CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES}")
if (TBB_NO_APPCONTAINER)
set(TBB_LIB_LINK_FLAGS ${TBB_LIB_LINK_FLAGS} /APPCONTAINER:NO)
endif()
endif()
if (TBB_WINDOWS_DRIVER)
# Since this is universal driver disable this variable
set(CMAKE_SYSTEM_PROCESSOR "")
# CMake define list additional libs, remove it for this build type
set(CMAKE_CXX_STANDARD_LIBRARIES "")
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} /D _UNICODE /DUNICODE /DWINAPI_FAMILY=WINAPI_FAMILY_APP /D__WRL_NO_DEFAULT_LIB__)
endif()
set(TBB_IPO_COMPILE_FLAGS $<$<NOT:$<CONFIG:Debug>>:/GL>)
set(TBB_IPO_LINK_FLAGS $<$<NOT:$<CONFIG:Debug>>:/LTCG /INCREMENTAL:NO>)
set(TBB_OPENMP_FLAG /openmp)
+112
View File
@@ -0,0 +1,112 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Save current location,
# see for details: https://cmake.org/cmake/help/latest/variable/CMAKE_CURRENT_LIST_DIR.html
set(_tbb_gen_cfg_path ${CMAKE_CURRENT_LIST_DIR})
include(CMakeParseArguments)
function(tbb_generate_config)
set(options HANDLE_SUBDIRS)
set(oneValueArgs INSTALL_DIR
SYSTEM_NAME
LIB_REL_PATH INC_REL_PATH DLL_REL_PATH
VERSION
TBB_BINARY_VERSION
TBBMALLOC_BINARY_VERSION
TBBMALLOC_PROXY_BINARY_VERSION
TBBBIND_BINARY_VERSION)
cmake_parse_arguments(tbb_gen_cfg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
get_filename_component(config_install_dir ${tbb_gen_cfg_INSTALL_DIR} ABSOLUTE)
file(MAKE_DIRECTORY ${config_install_dir})
file(TO_CMAKE_PATH "${tbb_gen_cfg_LIB_REL_PATH}" TBB_LIB_REL_PATH)
file(TO_CMAKE_PATH "${tbb_gen_cfg_DLL_REL_PATH}" TBB_DLL_REL_PATH)
file(TO_CMAKE_PATH "${tbb_gen_cfg_INC_REL_PATH}" TBB_INC_REL_PATH)
set(TBB_VERSION ${tbb_gen_cfg_VERSION})
set(TBB_COMPONENTS_BIN_VERSION "
set(_tbb_bin_version ${tbb_gen_cfg_TBB_BINARY_VERSION})
set(_tbbmalloc_bin_version ${tbb_gen_cfg_TBBMALLOC_BINARY_VERSION})
set(_tbbmalloc_proxy_bin_version ${tbb_gen_cfg_TBBMALLOC_PROXY_BINARY_VERSION})
set(_tbbbind_bin_version ${tbb_gen_cfg_TBBBIND_BINARY_VERSION})
")
if (tbb_gen_cfg_SYSTEM_NAME STREQUAL "Linux")
set(TBB_LIB_PREFIX "lib")
set(TBB_LIB_EXT "so.\${_\${_tbb_component}_bin_version}")
set(TBB_IMPLIB_RELEASE "")
set(TBB_IMPLIB_DEBUG "")
if (tbb_gen_cfg_HANDLE_SUBDIRS)
set(TBB_HANDLE_SUBDIRS "
if (CMAKE_SIZEOF_VOID_P STREQUAL \"8\")
set(_tbb_subdir intel64/gcc4.8)
else ()
set(_tbb_subdir ia32/gcc4.8)
endif()
")
endif()
elseif (tbb_gen_cfg_SYSTEM_NAME STREQUAL "Darwin")
set(TBB_LIB_PREFIX "lib")
set(TBB_LIB_EXT "\${_\${_tbb_component}_bin_version}.dylib")
set(TBB_IMPLIB_RELEASE "")
set(TBB_IMPLIB_DEBUG "")
elseif (tbb_gen_cfg_SYSTEM_NAME STREQUAL "Windows")
set(TBB_LIB_PREFIX "")
set(TBB_LIB_EXT "dll")
set(TBB_COMPILE_DEFINITIONS "
INTERFACE_COMPILE_DEFINITIONS \"__TBB_NO_IMPLICIT_LINKAGE=1\"")
# .lib files installed to TBB_LIB_REL_PATH (e.g. <prefix>/lib);
# .dll files installed to TBB_DLL_REL_PATH (e.g. <prefix>/bin);
# Expand TBB_LIB_REL_PATH here in IMPORTED_IMPLIB property and
# redefine it with TBB_DLL_REL_PATH value to properly fill IMPORTED_LOCATION property in TBBConfig.cmake.in template.
set(TBB_IMPLIB_RELEASE "
IMPORTED_IMPLIB_RELEASE \"\${_tbb_root}/${TBB_LIB_REL_PATH}/\${_tbb_subdir}/\${_tbb_component}\${_bin_version}.lib\"")
set(TBB_IMPLIB_DEBUG "
IMPORTED_IMPLIB_DEBUG \"\${_tbb_root}/${TBB_LIB_REL_PATH}/\${_tbb_subdir}/\${_tbb_component}\${_bin_version}_debug.lib\"")
set(TBB_LIB_REL_PATH ${TBB_DLL_REL_PATH})
if (tbb_gen_cfg_HANDLE_SUBDIRS)
set(TBB_HANDLE_SUBDIRS "
set(_tbb_subdir vc14)
if (WINDOWS_STORE)
set(_tbb_subdir \${_tbb_subdir}_uwp)
endif()
if (CMAKE_SIZEOF_VOID_P STREQUAL \"8\")
set(_tbb_subdir intel64/\${_tbb_subdir})
else ()
set(_tbb_subdir ia32/\${_tbb_subdir})
endif()
")
endif()
set(TBB_HANDLE_BIN_VERSION "
unset(_bin_version)
if (_tbb_component STREQUAL tbb)
set(_bin_version \${_tbb_bin_version})
endif()
")
else()
message(FATAL_ERROR "Unsupported OS name: ${tbb_system_name}")
endif()
configure_file(${_tbb_gen_cfg_path}/templates/TBBConfig.cmake.in ${config_install_dir}/TBBConfig.cmake @ONLY)
configure_file(${_tbb_gen_cfg_path}/templates/TBBConfigVersion.cmake.in ${config_install_dir}/TBBConfigVersion.cmake @ONLY)
endfunction()
+66
View File
@@ -0,0 +1,66 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
list(APPEND HWLOC_REQUIRED_VERSIONS 1_11 2 2_4)
foreach(hwloc_version ${HWLOC_REQUIRED_VERSIONS})
if (NOT WIN32)
set(CMAKE_HWLOC_${hwloc_version}_DLL_PATH STUB)
endif()
set(HWLOC_TARGET_NAME HWLOC::hwloc_${hwloc_version})
if (NOT TARGET ${HWLOC_TARGET_NAME} AND
CMAKE_HWLOC_${hwloc_version}_LIBRARY_PATH AND
CMAKE_HWLOC_${hwloc_version}_DLL_PATH AND
CMAKE_HWLOC_${hwloc_version}_INCLUDE_PATH
)
add_library(${HWLOC_TARGET_NAME} SHARED IMPORTED)
set_target_properties(${HWLOC_TARGET_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
"${CMAKE_HWLOC_${hwloc_version}_INCLUDE_PATH}")
if (WIN32)
set_target_properties(${HWLOC_TARGET_NAME} PROPERTIES
IMPORTED_LOCATION "${CMAKE_HWLOC_${hwloc_version}_DLL_PATH}"
IMPORTED_IMPLIB "${CMAKE_HWLOC_${hwloc_version}_LIBRARY_PATH}")
else()
set_target_properties(${HWLOC_TARGET_NAME} PROPERTIES
IMPORTED_LOCATION "${CMAKE_HWLOC_${hwloc_version}_LIBRARY_PATH}")
endif()
endif()
if (TARGET ${HWLOC_TARGET_NAME})
set(HWLOC_TARGET_EXPLICITLY_DEFINED TRUE)
endif()
endforeach()
unset(HWLOC_TARGET_NAME)
if (NOT HWLOC_TARGET_EXPLICITLY_DEFINED AND
# No hwloc auto detection for cross compilation
NOT CMAKE_CROSSCOMPILING
)
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(HWLOC hwloc)
if (HWLOC_FOUND)
if (HWLOC_VERSION VERSION_LESS 2)
set(TBBBIND_LIBRARY_NAME tbbbind)
elseif(HWLOC_VERSION VERSION_LESS 2.4)
set(TBBBIND_LIBRARY_NAME tbbbind_2_0)
else()
set(TBBBIND_LIBRARY_NAME tbbbind_2_4)
endif()
endif()
endif()
endif()
+104
View File
@@ -0,0 +1,104 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
option(TBB_VALGRIND_MEMCHECK "Enable scan for memory leaks using Valgrind" OFF)
if (NOT TBB_VALGRIND_MEMCHECK)
return()
endif()
add_custom_target(memcheck-all
COMMENT "Run memcheck on all tests")
find_program(VALGRIND_EXE valgrind)
if (NOT VALGRIND_EXE)
message(FATAL_ERROR "Valgrind executable is not found, add tool to PATH or turn off TBB_VALGRIND_MEMCHECK")
else()
message(STATUS "Found Valgrind to run memory leak scan")
endif()
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/memcheck)
function(_tbb_run_memcheck test_target)
set(target_name memcheck-${test_target})
add_custom_target(${target_name}
COMMAND ${VALGRIND_EXE} --leak-check=full --show-leak-kinds=all --log-file=${CMAKE_BINARY_DIR}/memcheck/${target_name}.log -v $<TARGET_FILE:${test_target}>)
add_dependencies(memcheck-all ${target_name})
endfunction()
add_custom_target(memcheck-short
COMMENT "Run memcheck scan on specified list")
# List of reasonable and quick enough tests to use in automated memcheck
add_dependencies(memcheck-short
memcheck-test_allocators
memcheck-test_arena_constraints
memcheck-test_dynamic_link
memcheck-test_concurrent_lru_cache
memcheck-conformance_concurrent_unordered_map
memcheck-conformance_concurrent_unordered_set
memcheck-conformance_concurrent_map
memcheck-conformance_concurrent_set
memcheck-conformance_concurrent_priority_queue
memcheck-conformance_concurrent_vector
memcheck-conformance_concurrent_queue
memcheck-conformance_concurrent_hash_map
memcheck-test_parallel_for
memcheck-test_parallel_for_each
memcheck-test_parallel_reduce
memcheck-test_parallel_sort
memcheck-test_parallel_invoke
memcheck-test_parallel_scan
memcheck-test_parallel_pipeline
memcheck-test_eh_algorithms
memcheck-test_task_group
memcheck-test_task_arena
memcheck-test_enumerable_thread_specific
memcheck-test_resumable_tasks
memcheck-conformance_mutex
memcheck-test_function_node
memcheck-test_multifunction_node
memcheck-test_broadcast_node
memcheck-test_buffer_node
memcheck-test_composite_node
memcheck-test_continue_node
memcheck-test_eh_flow_graph
memcheck-test_flow_graph
memcheck-test_flow_graph_priorities
memcheck-test_flow_graph_whitebox
memcheck-test_indexer_node
memcheck-test_join_node
memcheck-test_join_node_key_matching
memcheck-test_join_node_msg_key_matching
memcheck-test_priority_queue_node
memcheck-test_sequencer_node
memcheck-test_split_node
memcheck-test_tagged_msg
memcheck-test_overwrite_node
memcheck-test_write_once_node
memcheck-test_async_node
memcheck-test_input_node
memcheck-test_profiling
memcheck-test_concurrent_queue_whitebox
memcheck-test_intrusive_list
memcheck-test_semaphore
memcheck-test_environment_whitebox
memcheck-test_handle_perror
memcheck-test_hw_concurrency
memcheck-test_eh_thread
memcheck-test_global_control
memcheck-test_task
memcheck-test_concurrent_monitor
)
+21
View File
@@ -0,0 +1,21 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Note: current implementation uses CMAKE_BUILD_TYPE,
# this parameter is not defined for multi-config generators.
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VERSION "${TBB_VERSION}")
string(TOLOWER ${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}_${TBB_OUTPUT_DIR_BASE}_${CMAKE_BUILD_TYPE} CPACK_PACKAGE_FILE_NAME)
set(CPACK_GENERATOR ZIP)
include(CPack)
+21
View File
@@ -0,0 +1,21 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Add code signing as post-install step.
if (DEFINED TBB_SIGNTOOL)
install(CODE "
file(GLOB_RECURSE FILES_TO_SIGN \${CMAKE_INSTALL_PREFIX}/*${CMAKE_SHARED_LIBRARY_SUFFIX})
execute_process(COMMAND ${TBB_SIGNTOOL} \${FILES_TO_SIGN} ${TBB_SIGNTOOL_ARGS})
")
endif()
+38
View File
@@ -0,0 +1,38 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
find_package(PythonInterp 3.5 REQUIRED)
file(GLOB_RECURSE MODULES_LIST "${PYTHON_MODULE_BUILD_PATH}/*TBB.py*" )
list(LENGTH MODULES_LIST MODULES_COUNT)
if (MODULES_COUNT EQUAL 0)
message(FATAL_ERROR "Cannot find oneTBB Python module")
elseif (MODULES_COUNT GREATER 1)
message(WARNING "Found more than oneTBB Python modules, the only first found module will be tested")
endif()
list(GET MODULES_LIST 0 PYTHON_MODULE)
get_filename_component(PYTHON_MODULE_PATH ${PYTHON_MODULE} DIRECTORY)
execute_process(
COMMAND
${CMAKE_COMMAND} -E env LD_LIBRARY_PATH=${TBB_BINARIES_PATH}
${PYTHON_EXECUTABLE} -m tbb test
WORKING_DIRECTORY ${PYTHON_MODULE_PATH}
RESULT_VARIABLE CMD_RESULT
)
if (CMD_RESULT)
message(FATAL_ERROR "Error while test execution: ${cmd} error_code: ${CMD_RESULT}")
endif()
+38
View File
@@ -0,0 +1,38 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(TBB_SANITIZE ${TBB_SANITIZE} CACHE STRING "Sanitizer parameter passed to compiler/linker" FORCE)
# Possible values of sanitizer parameter for cmake-gui for convenience, user still can use any other value.
set_property(CACHE TBB_SANITIZE PROPERTY STRINGS "thread" "memory" "leak" "address -fno-omit-frame-pointer")
if (NOT TBB_SANITIZE)
return()
endif()
set(TBB_SANITIZE_OPTION -fsanitize=${TBB_SANITIZE})
# It is required to add sanitizer option to CMAKE_REQUIRED_LIBRARIES to make check_cxx_compiler_flag working properly:
# sanitizer option should be passed during the compilation phase as well as during the compilation.
set(CMAKE_REQUIRED_LIBRARIES "${TBB_SANITIZE_OPTION} ${CMAKE_REQUIRED_LIBRARIES}")
string(MAKE_C_IDENTIFIER ${TBB_SANITIZE_OPTION} FLAG_DISPLAY_NAME)
check_cxx_compiler_flag(${TBB_SANITIZE_OPTION} ${FLAG_DISPLAY_NAME})
if (NOT ${FLAG_DISPLAY_NAME})
message(FATAL_ERROR
"${TBB_SANITIZE_OPTION} is not supported by compiler ${CMAKE_CXX_COMPILER_ID}:${CMAKE_CXX_COMPILER_VERSION}, "
"please try another compiler or omit TBB_SANITIZE variable")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TBB_SANITIZE_OPTION}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TBB_SANITIZE_OPTION}")
@@ -0,0 +1,50 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(${CMAKE_CURRENT_LIST_DIR}/../config_generation.cmake)
# TBBConfig in TBB provided packages are expected to be placed into: <tbb-root>/lib/cmake/tbb*
set(TBB_ROOT_REL_PATH "../../..")
# Paths relative to TBB root directory
set(INC_REL_PATH "include")
set(LIB_REL_PATH "lib")
set(DLL_REL_PATH "redist")
# Parse version info
file(READ ${CMAKE_CURRENT_LIST_DIR}/../../include/oneapi/tbb/version.h _tbb_version_info)
string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" _tbb_ver_major "${_tbb_version_info}")
string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" _tbb_ver_minor "${_tbb_version_info}")
string(REGEX REPLACE ".*#define TBB_VERSION_PATCH ([0-9]+).*" "\\1" _tbb_ver_patch "${_tbb_version_info}")
string(REGEX REPLACE ".*#define __TBB_BINARY_VERSION ([0-9]+).*" "\\1" TBB_BINARY_VERSION "${_tbb_version_info}")
file(READ ${CMAKE_CURRENT_LIST_DIR}/../../CMakeLists.txt _tbb_cmakelist)
string(REGEX REPLACE ".*TBBMALLOC_BINARY_VERSION ([0-9]+).*" "\\1" TBBMALLOC_BINARY_VERSION "${_tbb_cmakelist}")
set(TBBMALLOC_PROXY_BINARY_VERSION ${TBBMALLOC_BINARY_VERSION})
string(REGEX REPLACE ".*TBBBIND_BINARY_VERSION ([0-9]+).*" "\\1" TBBBIND_BINARY_VERSION "${_tbb_cmakelist}")
set(COMMON_ARGS
TBB_ROOT_REL_PATH ${TBB_ROOT_REL_PATH}
INC_REL_PATH ${INC_REL_PATH}
LIB_REL_PATH ${LIB_REL_PATH}
VERSION ${_tbb_ver_major}.${_tbb_ver_minor}.${_tbb_ver_patch}
TBB_BINARY_VERSION ${TBB_BINARY_VERSION}
TBBMALLOC_BINARY_VERSION ${TBBMALLOC_BINARY_VERSION}
TBBMALLOC_PROXY_BINARY_VERSION ${TBBMALLOC_PROXY_BINARY_VERSION}
TBBBIND_BINARY_VERSION ${TBBBIND_BINARY_VERSION}
)
tbb_generate_config(INSTALL_DIR ${INSTALL_DIR}/linux SYSTEM_NAME Linux HANDLE_SUBDIRS ${COMMON_ARGS})
tbb_generate_config(INSTALL_DIR ${INSTALL_DIR}/windows SYSTEM_NAME Windows HANDLE_SUBDIRS DLL_REL_PATH ${DLL_REL_PATH} ${COMMON_ARGS})
tbb_generate_config(INSTALL_DIR ${INSTALL_DIR}/darwin SYSTEM_NAME Darwin ${COMMON_ARGS})
message(STATUS "TBBConfig files were created in ${INSTALL_DIR}")
+98
View File
@@ -0,0 +1,98 @@
# Copyright (c) 2017-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# It defines the following variables:
# TBB_<component>_FOUND
# TBB_IMPORTED_TARGETS
#
# TBBConfigVersion.cmake defines TBB_VERSION
#
# Initialize to default values
if (NOT TBB_IMPORTED_TARGETS)
set(TBB_IMPORTED_TARGETS "")
endif()
if (NOT TBB_FIND_COMPONENTS)
set(TBB_FIND_COMPONENTS "tbb;tbbmalloc;tbbmalloc_proxy")
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
set(TBB_FIND_REQUIRED_${_tbb_component} 1)
endforeach()
endif()
get_filename_component(_tbb_root "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
get_filename_component(_tbb_root "${_tbb_root}/@TBB_ROOT_REL_PATH@" ABSOLUTE)
set(TBB_INTERFACE_VERSION @TBB_INTERFACE_VERSION@)
@TBB_COMPONENTS_BIN_VERSION@
# Add components with internal dependencies: tbbmalloc_proxy -> tbbmalloc
list(FIND TBB_FIND_COMPONENTS tbbmalloc_proxy _tbbmalloc_proxy_ix)
if (NOT _tbbmalloc_proxy_ix EQUAL -1)
list(APPEND TBB_FIND_COMPONENTS tbbmalloc)
list(REMOVE_DUPLICATES TBB_FIND_COMPONENTS)
set(TBB_FIND_REQUIRED_tbbmalloc ${TBB_FIND_REQUIRED_tbbmalloc_proxy})
endif()
unset(_tbbmalloc_proxy_ix)
@TBB_HANDLE_SUBDIRS@
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
set(TBB_${_tbb_component}_FOUND 0)
@TBB_HANDLE_BIN_VERSION@
get_filename_component(_tbb_release_lib "${_tbb_root}/@TBB_LIB_REL_PATH@/${_tbb_subdir}/@TBB_LIB_PREFIX@${_tbb_component}${_bin_version}.@TBB_LIB_EXT@" ABSOLUTE)
if (NOT TBB_FIND_RELEASE_ONLY)
get_filename_component(_tbb_debug_lib "${_tbb_root}/@TBB_LIB_REL_PATH@/${_tbb_subdir}/@TBB_LIB_PREFIX@${_tbb_component}${_bin_version}_debug.@TBB_LIB_EXT@" ABSOLUTE)
endif()
if (EXISTS "${_tbb_release_lib}" OR EXISTS "${_tbb_debug_lib}")
if (NOT TARGET TBB::${_tbb_component})
add_library(TBB::${_tbb_component} SHARED IMPORTED)
get_filename_component(_tbb_include_dir "${_tbb_root}/@TBB_INC_REL_PATH@" ABSOLUTE)
set_target_properties(TBB::${_tbb_component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_tbb_include_dir}"@TBB_COMPILE_DEFINITIONS@)
unset(_tbb_current_realpath)
unset(_tbb_include_dir)
if (EXISTS "${_tbb_release_lib}")
set_target_properties(TBB::${_tbb_component} PROPERTIES
IMPORTED_LOCATION_RELEASE "${_tbb_release_lib}"@TBB_IMPLIB_RELEASE@)
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
endif()
if (EXISTS "${_tbb_debug_lib}")
set_target_properties(TBB::${_tbb_component} PROPERTIES
IMPORTED_LOCATION_DEBUG "${_tbb_debug_lib}"@TBB_IMPLIB_DEBUG@)
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
endif()
# Add internal dependencies for imported targets: TBB::tbbmalloc_proxy -> TBB::tbbmalloc
if (_tbb_component STREQUAL tbbmalloc_proxy)
set_target_properties(TBB::tbbmalloc_proxy PROPERTIES INTERFACE_LINK_LIBRARIES TBB::tbbmalloc)
endif()
endif()
list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
set(TBB_${_tbb_component}_FOUND 1)
elseif (TBB_FIND_REQUIRED AND TBB_FIND_REQUIRED_${_tbb_component})
message(STATUS "Missed required oneTBB component: ${_tbb_component}")
if (TBB_FIND_RELEASE_ONLY)
message(STATUS " ${_tbb_release_lib} must exist.")
else()
message(STATUS " one or both of:\n ${_tbb_release_lib}\n ${_tbb_debug_lib}\n files must exist.")
endif()
set(TBB_FOUND FALSE)
endif()
endforeach()
list(REMOVE_DUPLICATES TBB_IMPORTED_TARGETS)
unset(_tbb_release_lib)
unset(_tbb_debug_lib)
unset(_tbb_root)
+24
View File
@@ -0,0 +1,24 @@
# Copyright (c) 2017-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(PACKAGE_VERSION @TBB_VERSION@)
if ("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()
+35
View File
@@ -0,0 +1,35 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
option(TBB_TEST_SPEC "Generate test specification (Doxygen)" OFF)
if (TBB_TEST_SPEC)
find_package(Doxygen REQUIRED)
set(DOXYGEN_PREDEFINED_MACROS
"TBB_USE_EXCEPTIONS \
__TBB_RESUMABLE_TASKS \
__TBB_HWLOC_PRESENT \
__TBB_CPP17_DEDUCTION_GUIDES_PRESENT \
__TBB_CPP17_MEMORY_RESOURCE_PRESENT \
__TBB_CPP14_GENERIC_LAMBDAS_PRESENT"
)
add_custom_target(
test_spec ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
COMMENT "Generating test specification with Doxygen"
VERBATIM)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
endif()
+40
View File
@@ -0,0 +1,40 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Prevent double invocation.
if (MIPS_TOOLCHAIN_INCLUDED)
return()
endif()
set(MIPS_TOOLCHAIN_INCLUDED TRUE)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_PROCESSOR mips)
set(CMAKE_C_COMPILER ${CMAKE_FIND_ROOT_PATH}/bin/mips-img-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${CMAKE_FIND_ROOT_PATH}/bin/mips-img-linux-gnu-g++)
set(CMAKE_LINKER ${CMAKE_FIND_ROOT_PATH}/bin/mips-img-linux-gnu-ld)
# Define result for try_run used in find_package(Threads).
# In old CMake versions (checked on 3.5) there is invocation of try_run command in FindThreads.cmake module.
# It can't be executed on host system in case of cross-compilation for MIPS architecture.
# Define return code for this try_run as 0 since threads are expected to be available on target machine.
set(THREADS_PTHREAD_ARG "0" CACHE STRING "Result from TRY_RUN" FORCE)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -EL -mabi=64 -march=mips64r6 -mcrc -mfp64 -mmt -mtune=mips64r6 -ggdb -ffp-contract=off -mhard-float" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mvirt -mxpa" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mvirt -mxpa" CACHE INTERNAL "") # for tests
+44
View File
@@ -0,0 +1,44 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
macro(tbb_remove_compile_flag flag)
get_property(_tbb_compile_options DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS)
list(REMOVE_ITEM _tbb_compile_options ${flag})
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS ${_tbb_compile_options})
unset(_tbb_compile_options)
if (CMAKE_CXX_FLAGS)
string(REGEX REPLACE ${flag} "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
endif()
endmacro()
macro(tbb_install_target target)
install(TARGETS ${target}
EXPORT TBBTargets
LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR}
NAMELINK_SKIP
COMPONENT runtime
RUNTIME
DESTINATION ${CMAKE_INSTALL_BINDIR}
COMPONENT runtime
ARCHIVE
DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT devel)
install(TARGETS ${target}
LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR}
NAMELINK_ONLY
COMPONENT devel)
endmacro()
+48
View File
@@ -0,0 +1,48 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
option(TBB_INSTALL_VARS "Enable auto-generated vars installation" OFF)
if (WIN32)
set(TBB_VARS_TEMPLATE "windows/env/vars.bat.in")
elseif (APPLE)
set(TBB_VARS_TEMPLATE "mac/env/vars.sh.in")
else()
set(TBB_VARS_TEMPLATE "linux/env/vars.sh.in")
endif()
get_filename_component(TBB_VARS_TEMPLATE_NAME ${PROJECT_SOURCE_DIR}/integration/${TBB_VARS_TEMPLATE} NAME)
string(REPLACE ".in" "" TBB_VARS_NAME ${TBB_VARS_TEMPLATE_NAME})
macro(tbb_gen_vars target)
if (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
add_custom_command(TARGET ${target} POST_BUILD COMMAND
${CMAKE_COMMAND}
-DBINARY_DIR=${CMAKE_BINARY_DIR}
-DSOURCE_DIR=${PROJECT_SOURCE_DIR}
-DBIN_PATH=$<TARGET_FILE_DIR:${target}>
-DVARS_TEMPLATE=${TBB_VARS_TEMPLATE}
-DVARS_NAME=${TBB_VARS_NAME}
-DTBB_INSTALL_VARS=${TBB_INSTALL_VARS}
-DTBB_CMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
-P ${PROJECT_SOURCE_DIR}/integration/cmake/generate_vars.cmake
)
endif()
endmacro(tbb_gen_vars)
if (TBB_INSTALL_VARS)
install(PROGRAMS "${CMAKE_BINARY_DIR}/internal_install_vars"
DESTINATION env
RENAME ${TBB_VARS_NAME})
endif()
+2495
View File
File diff suppressed because it is too large Load Diff
+195
View File
@@ -0,0 +1,195 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.14 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="no" title=""/>
<tab type="pages" visible="no" title="" intro=""/>
<tab type="modules" visible="yes" title="" intro=""/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="no" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="Test Suites">
<tab type="filelist" visible="no" title="" intro=""/>
<tab type="globals" visible="no" title="" intro=""/>
</tab>
<tab type="user" url="@ref test_classification" visible="yes" title="Test Classification"/>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<classes visible="yes" title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<classes visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>
+35
View File
@@ -0,0 +1,35 @@
/// \page test_classification Test classification
/// The list of test classes attributed to test cases.
///
/// \section interface \\\#interface
/// This class of tests covers interface availability and checks basic
/// interface behavior.
///
/// \section requirement \\\#requirement
/// This class of tests covers one or more statements in the
/// specification document.
///
/// \section negative \\\#negative
/// This class of tests checks that input specified as invalid is
/// processed correctly. Additionally, this class of tests might
/// check imposibility to call particular interfaces that are not
/// described by the specification.
///
/// \section resource_usage \\\#resource usage
/// This class of tests checks correct resource usage and absence of
/// resource leaks.
///
/// \section boundary \\\#boundary
/// This class of tests checks boundary values, possible overflows, etc.
///
/// \section stress \\\#stress
/// This class of tests tries to detect synchronization and other issues
/// under heavy load and extensive usage of the functionality.
///
/// \section error_guessing \\\#error guessing
/// This class of tests tries to detect issues that implementation might
/// have but these issues cannot be deduced from the specification.
///
/// \section regression \\\#regression
/// This class of tests covers issues that were detected and fixed after
/// functionality release.
-145
View File
@@ -1,145 +0,0 @@
# Download links for old Intel(R) Threading Building Blocks packages
* 4.3 Update 6:
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150611oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150611oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150611oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150611oss_osx.tgz);
* 4.3 Update 5
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150424oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150424oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150424oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150424oss_osx.tgz);
* 4.3 Update 4
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150316oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150316oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150316oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150316oss_osx.tgz);
* 4.3 Update 3
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20150209oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20150209oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20150209oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20150209oss_osx.tgz);
* 4.3 Update 2
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20141204oss_src_0.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20141204oss_win_1.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20141204oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20141204oss_osx_1.tgz);
* 4.3 Update 1
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20141023oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20141023oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20141023oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20141023oss_osx.tgz);
* 4.3 Initial Release
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb43_20140724oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb43_20140724oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb43_20140724oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb43_20140724oss_osx.tgz);
* 4.2 Update 5
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20140601oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20140601oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20140601oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20140601oss_osx.tgz);
* 4.2 Update 4
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20140416oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20140416oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20140416oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20140416oss_osx.tgz);
* 4.2 Update 3
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20140122oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20140122oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20140122oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20140122oss_osx_0.tgz);
* 4.2 Update 2
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20131118oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20131118oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20131118oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20131118oss_osx.tgz);
* 4.2 Update 1
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20131003oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20131003oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20131003oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20131003oss_osx.tgz);
* 4.2 Initial Release
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20130725oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb42_20130725oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb42_20130725oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb42_20130725oss_osx.tgz);
* 4.1 Update 4
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130613oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20130613oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20130613oss_lin_0.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20130613oss_osx.tgz);
* 4.1 Update 3
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130314oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20130314oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20130314oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20130314oss_osx.tgz);
* 4.1 Update 2
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20130116oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20130116oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20130116oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20130116oss_osx.tgz);
* 4.1 Update 1
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20121003oss_src_1.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20121003oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20121003oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20121003oss_osx.tgz);
* 4.1 Initial Release
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb41_20120718oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb41_20120718oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb41_20120718oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb41_20120718oss_osx.tgz);
* 4.0 Update 5
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20120613oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20120613oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20120613oss_lin_0.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20120613oss_mac.tgz);
* 4.0 Update 4
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20120408oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20120408oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20120408oss_lin_0.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20120408oss_mac.tgz);
* 4.0 Update 3
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20120201oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20120201oss_win_2.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20120201oss_lin_1.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20120201oss_mac_0.tgz);
* 4.0 Update 2
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20111130oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20111130oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20111130oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20111130oss_mac.tgz);
* 4.0 Update 1
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20111003oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20111003oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20111003oss_lin_0.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20111003oss_mac.tgz);
* 4.0 Initial Release
[Source](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb40_20110809oss_src.tgz);
[Windows* OS](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/windows/tbb40_20110809oss_win.zip);
[Linux*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/linux/tbb40_20110809oss_lin.tgz);
[OS X*](https://www.threadingbuildingblocks.org/sites/default/files/software_releases/mac/tbb40_20110809oss_mac.tgz);
+159
View File
@@ -0,0 +1,159 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: false
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: true
DisableFormat: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ''
BasedOnStyle: google
ReflowComments: false
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 1
UseTab: Never
...
+75
View File
@@ -0,0 +1,75 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(tbb_examples CXX)
add_custom_target(build_examples)
add_custom_target(run_examples)
add_dependencies(run_examples build_examples)
add_custom_target(light_test_examples)
add_dependencies(light_test_examples build_examples)
macro(tbb_add_example subdir name)
add_subdirectory(${subdir}/${name})
add_dependencies(build_examples ${name})
add_dependencies(run_examples run_${name})
if (TARGET light_test_${name})
add_dependencies(light_test_examples light_test_${name})
else()
add_dependencies(light_test_examples run_${name})
endif()
endmacro()
tbb_add_example(concurrent_hash_map count_strings)
tbb_add_example(concurrent_priority_queue shortpath)
tbb_add_example(getting_started sub_string_finder)
tbb_add_example(graph binpack)
# TODO: Consider using FindMKL module
find_library(MKL_INTEL_LP64_LIB mkl_intel_lp64 PATHS ENV LIBRARY_PATH)
find_library(MKL_SEQUENTIAL_LIB mkl_sequential PATHS ENV LIBRARY_PATH)
find_library(MKL_CORE_LIB mkl_core PATHS ENV LIBRARY_PATH)
if(MKL_INTEL_LP64_LIB AND MKL_SEQUENTIAL_LIB AND MKL_CORE_LIB)
tbb_add_example(graph cholesky)
else()
message(WARNING "Intel(R) Math Kernel Library (Intel(R) MKL) libraries were not found, graph/cholesky example is excluded from the build.")
endif()
tbb_add_example(graph dining_philosophers)
tbb_add_example(graph fgbzip2)
tbb_add_example(graph logic_sim)
tbb_add_example(graph som)
tbb_add_example(parallel_for game_of_life)
tbb_add_example(parallel_for polygon_overlay)
tbb_add_example(parallel_for seismic)
tbb_add_example(parallel_for tachyon)
tbb_add_example(parallel_for_each parallel_preorder)
tbb_add_example(parallel_pipeline square)
tbb_add_example(parallel_reduce convex_hull)
tbb_add_example(parallel_reduce primes)
tbb_add_example(task_arena fractal)
tbb_add_example(task_group sudoku)
tbb_add_example(test_all fibonacci)
+40
View File
@@ -0,0 +1,40 @@
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
This directory contains example usages of oneAPI Threading Building Blocks.
| Code sample name | Description
|:--- |:---
| getting_started/sub_string_finder | Example referenced by the [oneAPI Threading Building Blocks Get Started Guide](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html). Finds largest matching substrings.
| concurrent_hash_map/count_strings | Concurrently inserts strings into a `concurrent_hash_map` container.
| concurrent_priority_queue/shortpath | Solves the single source shortest path problem using a `concurrent_priority_queue` container.
| graph/binpack | A solution to the binpacking problem using a `queue_node`, a `buffer_node` and `function_node`s.
| graph/cholesky | Several versions of Cholesky Factorization algorithm implementation.
| graph/dining_philosophers | An implementation of dining philosophers in graph using the reserving `join_node`.
| graph/fgbzip2 | A parallel implementation of bzip2 block-sorting file compressor.
| graph/logic_sim | An example of a collection of digital logic gates that can be easily composed into larger circuits.
| graph/som | An example of a Kohonen Self-Organizing Map using cancellation.
| parallel_for/game_of_life | Game of life overlay.
| parallel_for/polygon_overlay | polygon overlay.
| parallel_for/seismic | Parallel seismic wave simulation.
| parallel_for/tachyon | Parallel 2-D raytracer/renderer.
| parallel_for_each/parallel_preorder | Parallel preorder traversal of a graph.
| parallel_pipeline/square | Another string transformation example that squares numbers read from a file.
| parallel_reduce/convex_hull | Parallel version of convex hull algorithm (quick hull).
| parallel_reduce/primes | Parallel version of the Sieve of Eratosthenes.
| task_arena/fractal |The example calculates two classical Mandelbrot fractals with different concurrency limits.
| task_group/sudoku | Compute all solutions for a Sudoku board.
| test_all/fibonacci | Compute Fibonacci numbers in different ways.
## System Requirements
"Refer to the [System Requirements](https://software.intel.com/content/www/us/en/develop/articles/intel-oneapi-threading-building-blocks-system-requirements.html) for the list of supported hardware and software".
### Graphical User Interface (GUI)
Some examples (fractal, seismic, tachyon, polygon_overlay) supports different GUI modes, which may be defined via the `EXAMPLES_UI_MODE` CMake variable. Supported values are:
- Cross-platform:
- `con` - Console mode (Default).
- Windows:
- `gdi` - `GDI+` based implementation.
- `d2d` - `Direct 2D` based implementation. May offer superior performance, but can only be used if the Microsoft* DirectX* SDK is installed on your system(`DXSDK_DIR` should be defined).
- Linux:
- `x` - `X11` based implementation. Also `libXext` may be required to display the output correctly.
- MacOS:
- `mac` - `OpenGL` based implementation. Also requires the `Foundation` and `Cocoa` libraries availability.
+48
View File
@@ -0,0 +1,48 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
macro(set_common_project_settings required_components)
# Path to common headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../)
if (NOT TARGET TBB::tbb)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../common/cmake/modules)
find_package(TBB REQUIRED COMPONENTS ${required_components})
endif()
find_package(Threads REQUIRED)
# ---------------------------------------------------------------------------------------------------------
# Handle C++ standard version.
if (NOT MSVC) # no need to cover MSVC as it uses C++14 by default.
if (NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
endif()
if (CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION) # if standard option was detected by CMake
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
endif()
set(CMAKE_CXX_EXTENSIONS OFF) # use -std=c++... instead of -std=gnu++...
# ---------------------------------------------------------------------------------------------------------
endmacro()
macro(add_execution_target TARGET_NAME TARGET_DEPENDENCIES EXECUTABLE ARGS)
if (WIN32)
add_custom_target(${TARGET_NAME} set "PATH=$<TARGET_FILE_DIR:TBB::tbb>\\;$ENV{PATH}" & ${EXECUTABLE} ${ARGS})
else()
add_custom_target(${TARGET_NAME} ${EXECUTABLE} ${ARGS})
endif()
add_dependencies(${TARGET_NAME} ${TARGET_DEPENDENCIES})
endmacro()
@@ -0,0 +1,89 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
include(FindPackageHandleStandardArgs)
# Firstly search for TBB in config mode (i.e. search for TBBConfig.cmake).
find_package(TBB QUIET CONFIG)
if (TBB_FOUND)
find_package_handle_standard_args(TBB CONFIG_MODE)
return()
endif()
if (NOT TBB_FIND_COMPONENTS)
set(TBB_FIND_COMPONENTS tbb tbbmalloc)
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
set(TBB_FIND_REQUIRED_${_tbb_component} 1)
endforeach()
endif()
if (WIN32)
list(APPEND ADDITIONAL_LIB_DIRS ENV PATH ENV LIB)
list(APPEND ADDITIONAL_INCLUDE_DIRS ENV INCLUDE ENV CPATH)
else()
list(APPEND ADDITIONAL_LIB_DIRS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
list(APPEND ADDITIONAL_INCLUDE_DIRS ENV CPATH ENV C_INCLUDE_PATH ENV CPLUS_INCLUDE_PATH ENV INCLUDE_PATH)
endif()
find_path(_tbb_include_dir NAMES tbb/tbb.h PATHS ${ADDITIONAL_INCLUDE_DIRS})
if (_tbb_include_dir)
# TODO: consider TBB_VERSION handling
set(_TBB_BUILD_MODES RELEASE DEBUG)
set(_TBB_DEBUG_SUFFIX _debug)
foreach (_tbb_component ${TBB_FIND_COMPONENTS})
if (NOT TARGET TBB::${_tbb_component})
add_library(TBB::${_tbb_component} SHARED IMPORTED)
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${_tbb_include_dir})
foreach(_TBB_BUILD_MODE ${_TBB_BUILD_MODES})
set(_tbb_component_lib_name ${_tbb_component}${_TBB_${_TBB_BUILD_MODE}_SUFFIX})
if (WIN32)
find_library(${_tbb_component_lib_name}_lib ${_tbb_component_lib_name} PATHS ${ADDITIONAL_LIB_DIRS})
find_file(${_tbb_component_lib_name}_dll ${_tbb_component_lib_name}.dll PATHS ${ADDITIONAL_LIB_DIRS})
set_target_properties(TBB::${_tbb_component} PROPERTIES
IMPORTED_LOCATION_${_TBB_BUILD_MODE} "${${_tbb_component_lib_name}_dll}"
IMPORTED_IMPLIB_${_TBB_BUILD_MODE} "${${_tbb_component_lib_name}_lib}"
)
else()
find_library(${_tbb_component_lib_name}_so ${_tbb_component_lib_name} PATHS ${ADDITIONAL_LIB_DIRS})
set_target_properties(TBB::${_tbb_component} PROPERTIES
IMPORTED_LOCATION_${_TBB_BUILD_MODE} "${${_tbb_component_lib_name}_so}"
)
endif()
if (${_tbb_component_lib_name}_lib AND ${_tbb_component_lib_name}_dll OR ${_tbb_component_lib_name}_so)
set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${_TBB_BUILD_MODE})
list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
set(TBB_${_tbb_component}_FOUND 1)
endif()
unset(${_tbb_component_lib_name}_lib CACHE)
unset(${_tbb_component_lib_name}_dll CACHE)
unset(${_tbb_component_lib_name}_so CACHE)
unset(_tbb_component_lib_name)
endforeach()
endif()
endforeach()
unset(_TBB_BUILD_MODESS)
unset(_TBB_DEBUG_SUFFIX)
endif()
unset(_tbb_include_dir CACHE)
list(REMOVE_DUPLICATES TBB_IMPORTED_TARGETS)
find_package_handle_standard_args(TBB
REQUIRED_VARS TBB_IMPORTED_TARGETS
HANDLE_COMPONENTS)
+127
View File
@@ -0,0 +1,127 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
set(EXAMPLES_UI_MODE "con" CACHE STRING "EXAMPLES_UI_MODE")
if (WIN32)
set_property(CACHE EXAMPLES_UI_MODE PROPERTY STRINGS "con" "gdi" "d2d")
elseif (APPLE)
set_property(CACHE EXAMPLES_UI_MODE PROPERTY STRINGS "con" "mac")
else()
set_property(CACHE EXAMPLES_UI_MODE PROPERTY STRINGS "con" "x")
endif()
get_property(_available_ui_modes CACHE EXAMPLES_UI_MODE PROPERTY STRINGS)
list(FIND _available_ui_modes ${EXAMPLES_UI_MODE} _find_index)
if (NOT _find_index EQUAL -1)
add_library(UI_LIB_${PROJECT_NAME} STATIC ${CMAKE_CURRENT_LIST_DIR}/${EXAMPLES_UI_MODE}video.cpp)
if (EXAMPLES_UI_MODE STREQUAL "mac")
enable_language(C)
add_library(UI_LIB_OBJECT_${PROJECT_NAME} OBJECT
${CMAKE_CURRENT_LIST_DIR}/xcode/tbbExample/main.m
${CMAKE_CURRENT_LIST_DIR}/xcode/tbbExample/OpenGLView.m
${CMAKE_CURRENT_LIST_DIR}/xcode/tbbExample/tbbAppDelegate.m
)
target_sources(UI_LIB_${PROJECT_NAME} PUBLIC $<TARGET_OBJECTS:UI_LIB_OBJECT_${PROJECT_NAME}>)
endif()
else()
string(REPLACE ";" ", " _available_ui_modes "${_available_ui_modes}")
message(FATAL_ERROR
"Selected UI mode (${EXAMPLES_UI_MODE}) is not supported on ${CMAKE_SYSTEM_NAME}.
Supported UI modes: ${_available_ui_modes}"
)
endif()
macro(set_gdi_ui_project_settings)
find_program(RC rc REQUIRED)
add_custom_command(TARGET UI_LIB_${PROJECT_NAME} PRE_BUILD COMMAND
${RC} /r -fo ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.res ${PROJECT_SOURCE_DIR}/gui/${PROJECT_NAME}.rc
)
set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE)
if (COMMAND target_link_options)
target_link_options(UI_LIB_${PROJECT_NAME} PUBLIC ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.res)
else()
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.res)
endif()
endmacro()
macro(set_d2d_ui_project_settings)
set_gdi_ui_project_settings()
if (IS_DIRECTORY $ENV{DXSDK_DIR})
target_include_directories(UI_LIB_${PROJECT_NAME} PUBLIC $ENV{DXSDK_DIR}\\include)
target_link_directories(UI_LIB_${PROJECT_NAME} PUBLIC $ENV{DXSDK_DIR}\\lib\\x64)
else()
message(FATAL_ERROR "Cannot find the DirectX library (required by the 'd2d' UI mode)")
endif()
endmacro()
macro(set_x_ui_project_settings)
find_package(X11 REQUIRED)
target_link_libraries(UI_LIB_${PROJECT_NAME} PUBLIC ${X11_LIBRARIES})
target_include_directories(UI_LIB_${PROJECT_NAME} PUBLIC ${X11_INCLUDE_DIR})
find_library(LIB_Xext Xext PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
if (LIB_Xext)
target_link_libraries(UI_LIB_${PROJECT_NAME} PUBLIC ${LIB_Xext})
else()
target_compile_definitions(UI_LIB_${PROJECT_NAME} PUBLIC -DX_NOSHMEM)
endif()
endmacro()
macro(set_mac_ui_project_settings)
find_package(OpenGL REQUIRED)
find_library(FOUNDATION_LIBRARY Foundation PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
if (NOT FOUNDATION_LIBRARY)
message(FATAL_ERROR "Cannot find the Foundation library (required by the 'mac' UI mode)")
endif()
find_library(COCOA_LIBRARY Cocoa PATHS ENV LIBRARY_PATH ENV LD_LIBRARY_PATH ENV DYLD_LIBRARY_PATH)
if (NOT COCOA_LIBRARY)
message(FATAL_ERROR "Cannot find the Cocoa library (required by the 'mac' UI mode)")
endif()
target_link_libraries(UI_LIB_${PROJECT_NAME} PUBLIC ${OPENGL_LIBRARIES} ${FOUNDATION_LIBRARY} ${COCOA_LIBRARY})
target_include_directories(UI_LIB_${PROJECT_NAME} PUBLIC ${OPENGL_INCLUDE_DIR})
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/Resources)
file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/MacOS)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../../common/gui/xcode/tbbExample/PkgInfo DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../../common/gui/xcode/tbbExample/en.lproj DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/Resources)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../common/gui/xcode/tbbExample/tbbExample-Info.plist ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MacUI/${PROJECT_NAME}.app/Contents/Info.plist COPYONLY)
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "MacUI/${PROJECT_NAME}.app/Contents/MacOS/")
endmacro()
if (NOT _find_index EQUAL -1)
if ("${EXAMPLES_UI_MODE}" STREQUAL "gdi")
set_gdi_ui_project_settings()
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "d2d")
set_d2d_ui_project_settings()
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "mac")
set_mac_ui_project_settings()
elseif ("${EXAMPLES_UI_MODE}" STREQUAL "x")
set_x_ui_project_settings()
endif()
endif()
unset(_available_ui_modes)
unset(_find_index)
+149
View File
@@ -0,0 +1,149 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cassert>
#include <stdio.h>
#include "video.hpp"
unsigned int *g_pImg = 0;
int g_sizex, g_sizey;
static video *g_video = 0;
static int g_fps = 0;
#if _WIN32 || _WIN64
static DWORD g_msec = 0;
#ifdef _WINDOWS
HINSTANCE video::win_hInstance = 0;
int video::win_iCmdShow = 0;
void video::win_set_class(WNDCLASSEX &wcex) {}
void video::win_load_accelerators(int idc) {}
#endif //_WINDOWS
#else
#include <sched.h>
#include <sys/time.h>
struct timeval g_time;
#endif //_WIN32||_WIN64
#define CALC_FPS_ENABLED ((WINAPI_FAMILY != WINAPI_FAMILY_APP) && (!__ANDROID__))
video::video()
// OpenGL* RGBA byte order for little-endian CPU
: depth(24),
red_shift(0),
green_shift(8),
blue_shift(16),
red_mask(0xff),
green_mask(0xff00),
blue_mask(0xff0000) {
assert(g_video == 0);
g_video = this;
title = "Video";
updating = calc_fps = false;
}
bool video::init_window(int x, int y) {
g_sizex = x;
g_sizey = y;
g_pImg = new unsigned int[x * y];
running = true;
return false;
}
bool video::init_console() {
running = true;
return true;
}
void video::terminate() {
#if CALC_FPS_ENABLED
if (calc_fps) {
double fps = g_fps;
#if _WIN32 || _WIN64
fps /= (GetTickCount() - g_msec) / 1000.0;
#else
struct timezone tz;
struct timeval end_time;
gettimeofday(&end_time, &tz);
fps /= (end_time.tv_sec + 1.0 * end_time.tv_usec / 1000000.0) -
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0);
#endif
printf("%s: %.1f fps\n", title, fps);
}
#endif
g_video = 0;
running = false;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
video::~video() {
if (g_video)
terminate();
}
//! Count and display FPS count in titlebar
bool video::next_frame() {
#if CALC_FPS_ENABLED
if (calc_fps) {
if (!g_fps) {
#if _WIN32 || _WIN64
g_msec = GetTickCount();
#else
struct timezone tz;
gettimeofday(&g_time, &tz);
#endif
}
g_fps++;
}
#endif
return running;
}
//! Do standard loop
void video::main_loop() {
on_process();
}
//! Change window title
void video::show_title() {}
///////////////////////////////////////////// public methods of video class ///////////////////////
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
: base_index(y * g_sizex + x),
max_index(g_sizex * g_sizey),
index_stride(g_sizex),
pixel_depth(24),
ptr32(g_pImg),
start_x(x),
start_y(y),
size_x(sizex),
size_y(sizey) {
assert(x < g_sizex);
assert(y < g_sizey);
assert(x + sizex <= g_sizex);
assert(y + sizey <= g_sizey);
index = base_index; // current index
}
void drawing_area::update() {}
+202
View File
@@ -0,0 +1,202 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// common Windows parts
#include "winvideo.hpp"
// and another headers
#include <cassert>
#include <stdio.h>
#include <dxsdkver.h>
#if _DXSDK_PRODUCT_MAJOR < 9
#error DXSDK Version 9 and above required.
#endif
#include <d2d1.h>
#include <d2d1helper.h>
#pragma comment(lib, "d2d1.lib")
ID2D1Factory *m_pD2DFactory;
ID2D1HwndRenderTarget *m_pRenderTarget;
ID2D1Bitmap *m_pBitmap;
D2D1_SIZE_U bitmapSize;
HANDLE g_hVSync;
#include <DXErr.h>
#pragma comment(lib, "DxErr.lib")
//! Create a dialog box and tell the user what went wrong
bool DisplayError(LPSTR lpstrErr, HRESULT hres) {
if (hres != S_OK) {
static bool InError = false;
int retval = 0;
if (!InError) {
InError = true;
const char *message = hres ? DXGetErrorString(hres) : 0;
retval =
MessageBoxA(g_hAppWnd, lpstrErr, hres ? message : "Error!", MB_OK | MB_ICONERROR);
InError = false;
}
}
return false;
}
void DrawBitmap() {
HRESULT hr = S_OK;
if (m_pRenderTarget) {
m_pRenderTarget->BeginDraw();
if (m_pBitmap)
hr = m_pBitmap->CopyFromMemory(NULL, (BYTE *)g_pImg, 4 * g_sizex);
DisplayError("DrawBitmap error", hr);
m_pRenderTarget->DrawBitmap(m_pBitmap);
m_pRenderTarget->EndDraw();
}
return;
}
inline void mouse(int k, LPARAM lParam) {
int x = (int)LOWORD(lParam);
int y = (int)HIWORD(lParam);
RECT rc;
GetClientRect(g_hAppWnd, &rc);
g_video->on_mouse(x * g_sizex / (rc.right - rc.left), y * g_sizey / (rc.bottom - rc.top), k);
}
//! Win event processing function
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
switch (iMsg) {
case WM_MOVE:
// Check to make sure our window exists before we tell it to repaint.
// This will fail the first time (while the window is being created).
if (hwnd) {
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
return 0L;
case WM_SIZE:
case WM_PAINT:
if (g_video->running && g_video->updating) {
DrawBitmap();
Sleep(0);
}
break;
// Process all mouse and keyboard events
case WM_LBUTTONDOWN: mouse(1, lParam); break;
case WM_LBUTTONUP: mouse(-1, lParam); break;
case WM_RBUTTONDOWN: mouse(2, lParam); break;
case WM_RBUTTONUP: mouse(-2, lParam); break;
case WM_MBUTTONDOWN: mouse(3, lParam); break;
case WM_MBUTTONUP: mouse(-3, lParam); break;
case WM_CHAR: g_video->on_key((int)wParam); break;
// some useless stuff
case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop
case WM_DISPLAYCHANGE: return 0;
// Now, shut down the window...
case WM_DESTROY: PostQuitMessage(0); return 0;
}
// call user defined proc, if exists
return g_pUserProc ? g_pUserProc(hwnd, iMsg, wParam, lParam)
: DefWindowProc(hwnd, iMsg, wParam, lParam);
}
bool video::init_window(int sizex, int sizey) {
assert(win_hInstance != 0);
g_sizex = sizex;
g_sizey = sizey;
if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, false)) {
DisplayError("Unable to initialize the program's window.");
return false;
}
ShowWindow(g_hAppWnd, SW_SHOW);
g_pImg = new unsigned int[sizex * sizey];
HRESULT hr = S_OK;
hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
// Create a Direct2D render target.
if (SUCCEEDED(hr) && !m_pRenderTarget) {
RECT rc;
GetClientRect(g_hAppWnd, &rc);
bitmapSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
hr = m_pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(g_hAppWnd, bitmapSize),
&m_pRenderTarget);
if (SUCCEEDED(hr) && !m_pBitmap) {
D2D1_PIXEL_FORMAT pixelFormat =
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
D2D1_BITMAP_PROPERTIES bitmapProperties;
bitmapProperties.pixelFormat = pixelFormat;
m_pRenderTarget->GetDpi(&bitmapProperties.dpiX, &bitmapProperties.dpiY);
m_pRenderTarget->CreateBitmap(bitmapSize, bitmapProperties, &m_pBitmap);
m_pRenderTarget->DrawBitmap(m_pBitmap);
}
}
running = true;
return true;
}
void video::terminate() {
if (m_pBitmap)
m_pBitmap->Release();
if (m_pRenderTarget)
m_pRenderTarget->Release();
if (m_pD2DFactory)
m_pD2DFactory->Release();
g_video = 0;
running = false;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
//////////// drawing area constructor & destructor /////////////
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
: base_index(y * g_sizex + x),
max_index(g_sizex * g_sizey),
index_stride(g_sizex),
pixel_depth(24),
ptr32(g_pImg),
start_x(x),
start_y(y),
size_x(sizex),
size_y(sizey) {
assert(x < g_sizex);
assert(y < g_sizey);
assert(x + sizex <= g_sizex);
assert(y + sizey <= g_sizey);
index = base_index; // current index
}
void drawing_area::update() {
if (g_video->updating) {
RECT r;
r.left = start_x;
r.right = start_x + size_x;
r.top = start_y;
r.bottom = start_y + size_y;
InvalidateRect(g_hAppWnd, &r, false);
}
}
+168
View File
@@ -0,0 +1,168 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// common Windows parts
#include "winvideo.hpp"
// include GDI+ headers
#include <gdiplus.h>
// and another headers
#include <stdio.h>
// tag linking library
#pragma comment(lib, "gdiplus.lib")
// global specific variables
Gdiplus::Bitmap* g_pBitmap; // main drawing bitmap
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartupInput gdiplusStartupInput; // GDI+
//! display system error
bool DisplayError(LPSTR lpstrErr, HRESULT hres) {
static bool InError = false;
int retval = 0;
if (!InError) {
InError = true;
LPCSTR lpMsgBuf;
if (!hres)
hres = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
hres,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
retval = MessageBox(g_hAppWnd, lpstrErr, lpMsgBuf, MB_OK | MB_ICONERROR);
LocalFree((HLOCAL)lpMsgBuf);
InError = false;
}
return false;
}
//! Win event processing function
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
switch (iMsg) {
case WM_MOVE:
// Check to make sure our window exists before we tell it to repaint.
// This will fail the first time (while the window is being created).
if (hwnd) {
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
return 0L;
case WM_PAINT: {
PAINTSTRUCT ps;
Gdiplus::Graphics graphics(BeginPaint(hwnd, &ps));
// redraw just requested area. This call is as fast as simple DrawImage() call.
if (g_video->updating)
graphics.DrawImage(g_pBitmap,
ps.rcPaint.left,
ps.rcPaint.top,
ps.rcPaint.left,
ps.rcPaint.top,
ps.rcPaint.right,
ps.rcPaint.bottom,
Gdiplus::UnitPixel);
EndPaint(hwnd, &ps);
}
return 0L;
// Process all mouse and keyboard events
case WM_LBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 1); break;
case WM_LBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -1); break;
case WM_RBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 2); break;
case WM_RBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -2); break;
case WM_MBUTTONDOWN: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), 3); break;
case WM_MBUTTONUP: g_video->on_mouse((int)LOWORD(lParam), (int)HIWORD(lParam), -3); break;
case WM_CHAR: g_video->on_key((int)wParam); break;
// some useless stuff
case WM_ERASEBKGND: return 1; // keeps erase-background events from happening, reduces chop
case WM_DISPLAYCHANGE: return 0;
// Now, shut down the window...
case WM_DESTROY: PostQuitMessage(0); return 0;
}
// call user defined proc, if exists
return g_pUserProc ? g_pUserProc(hwnd, iMsg, wParam, lParam)
: DefWindowProc(hwnd, iMsg, wParam, lParam);
}
///////////// video functions ////////////////
bool video::init_window(int sizex, int sizey) {
assert(win_hInstance != 0);
g_sizex = sizex;
g_sizey = sizey;
if (!WinInit(win_hInstance, win_iCmdShow, gWndClass, title, true)) {
DisplayError("Unable to initialize the program's window.");
return false;
}
ShowWindow(g_hAppWnd, SW_SHOW);
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
g_pImg = new unsigned int[sizex * sizey];
g_pBitmap =
new Gdiplus::Bitmap(g_sizex, g_sizey, 4 * g_sizex, PixelFormat32bppRGB, (BYTE*)g_pImg);
running = true;
return true;
}
void video::terminate() {
if (g_pBitmap) {
delete g_pBitmap;
g_pBitmap = 0;
}
Gdiplus::GdiplusShutdown(gdiplusToken);
g_video = 0;
running = false;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
//////////// drawing area constructor & destructor /////////////
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
: base_index(y * g_sizex + x),
max_index(g_sizex * g_sizey),
index_stride(g_sizex),
pixel_depth(24),
ptr32(g_pImg),
start_x(x),
start_y(y),
size_x(sizex),
size_y(sizey) {
assert(x < g_sizex);
assert(y < g_sizey);
assert(x + sizex <= g_sizex);
assert(y + sizey <= g_sizey);
index = base_index; // current index
}
void drawing_area::update() {
if (g_video->updating) {
RECT r;
r.left = start_x;
r.right = start_x + size_x;
r.top = start_y;
r.bottom = start_y + size_y;
InvalidateRect(g_hAppWnd, &r, false);
}
}
+188
View File
@@ -0,0 +1,188 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "video.hpp"
#include <cassert>
#include <stdio.h>
#include <iostream>
#include <pthread.h>
unsigned int *g_pImg = 0;
int g_sizex = 0, g_sizey = 0;
static video *g_video = 0;
static int g_fps = 0;
char *window_title = NULL;
#define WINDOW_TITLE_SIZE 256
int cocoa_update = 0;
#include <sched.h>
#include <sys/time.h>
struct timeval g_time;
video::video()
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__
: depth(24),
red_shift(0),
green_shift(8),
blue_shift(16),
red_mask(0xff),
green_mask(0xff00),
blue_mask(0xff0000)
#else
: depth(24),
red_shift(16),
green_shift(8),
blue_shift(0),
red_mask(0xff0000),
green_mask(0xff00),
blue_mask(0xff)
#endif
{
assert(g_video == 0);
g_video = this;
title = "Video";
cocoa_update = 1;
updating = true;
calc_fps = false;
}
bool video::init_window(int x, int y) {
g_sizex = x;
g_sizey = y;
g_pImg = new unsigned int[x * y];
if (window_title == NULL)
window_title = (char *)malloc(WINDOW_TITLE_SIZE);
strncpy(window_title, title, WINDOW_TITLE_SIZE - 1);
running = true;
return true;
}
bool video::init_console() {
running = true;
return true;
}
void video::terminate() {
if (calc_fps) {
double fps = g_fps;
struct timezone tz;
struct timeval end_time;
gettimeofday(&end_time, &tz);
fps /= (end_time.tv_sec + 1.0 * end_time.tv_usec / 1000000.0) -
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0);
printf("%s: %.1f fps\n", title, fps);
}
g_video = 0;
running = false;
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
}
}
video::~video() {
if (g_video)
terminate();
}
//! Count and display FPS count in titlebar
bool video::next_frame() {
if (calc_fps) {
if (!g_fps) {
struct timezone tz;
gettimeofday(&g_time, &tz);
}
g_fps++;
}
struct timezone tz;
struct timeval now_time;
gettimeofday(&now_time, &tz);
double sec = ((now_time.tv_sec + 1.0 * now_time.tv_usec / 1000000.0) -
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0));
if (sec > 1) {
if (calc_fps) {
memcpy(&g_time, &now_time, sizeof(g_time));
int fps;
fps = g_fps / sec;
cocoa_update = (int)updating;
snprintf(window_title,
WINDOW_TITLE_SIZE,
"%s%s: %d fps",
title,
updating ? "" : " (no updating)",
int(fps));
g_fps = 0;
}
}
return running;
}
void *thread_func(void *) {
g_video->on_process();
exit(EXIT_SUCCESS);
}
extern "C" void on_mouse_func(int x, int y, int k) {
g_video->on_mouse(x, y, k);
return;
}
extern "C" void on_key_func(int x) {
g_video->on_key(x);
return;
}
extern "C" int cocoa_main(int argc, char *argv[]);
//! Do standard loop
void video::main_loop() {
pthread_t handle;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&handle, &attr, &thread_func, (void *)NULL);
pthread_detach(handle);
cocoa_main(0, NULL);
}
//! Change window title
void video::show_title() {
if (title)
strncpy(window_title, title, WINDOW_TITLE_SIZE);
return;
}
///////////////////////////////////////////// public methods of video class ///////////////////////
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
: base_index(y * g_sizex + x),
max_index(g_sizex * g_sizey),
index_stride(g_sizex),
pixel_depth(24),
ptr32(g_pImg),
start_x(x),
start_y(y),
size_x(sizex),
size_y(sizey) {
assert(x < g_sizex);
assert(y < g_sizey);
assert(x + sizex <= g_sizex);
assert(y + sizey <= g_sizey);
index = base_index; // current index
}
void drawing_area::update() {
//nothing to do, updating via timer in cocoa part.
}
+249
View File
@@ -0,0 +1,249 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef TBB_examples_video_H
#define TBB_examples_video_H
#include <cassert>
#include <cstddef>
#if _MSC_VER
#include <stddef.h> // for uintptr_t
#else
#include <stdint.h> // for uintptr_t
#endif
#if _WIN32 || _WIN64
#include <windows.h>
#else
#include <unistd.h>
#endif
typedef unsigned int color_t;
typedef unsigned char colorcomp_t;
typedef signed char depth_t;
//! Class for getting access to drawing memory
class drawing_memory {
uintptr_t my_address;
public:
depth_t pixel_depth;
int sizex, sizey;
//! Get drawing memory
inline char *get_address() const {
return reinterpret_cast<char *>(my_address);
}
//! Get drawing memory size
inline int get_size() const {
return ((pixel_depth > 16) ? 4 : 2) * sizex * sizey;
}
//! Set drawing memory
inline void set_address(char *mem) {
my_address = reinterpret_cast<uintptr_t>(mem);
}
friend class drawing_area;
friend class video;
};
//! Simple proxy class for managing of different video systems
class video {
//! colorspace information
depth_t depth, red_shift, green_shift, blue_shift;
color_t red_mask, green_mask, blue_mask;
friend class drawing_area;
public:
//! Constructor
video();
//! Destructor
~video();
//! member to set window name
const char *title;
//! true is enable to show fps
bool calc_fps;
//! if true: on windows fork processing thread for on_process(), on non-windows note that next_frame() is called concurrently.
bool threaded;
//! true while running within main_loop()
bool running;
//! if true, do gui updating
bool updating;
//! initialize graphical video system
bool init_window(int sizex, int sizey);
//! initialize console. returns true if console is available
bool init_console();
//! terminate video system
void terminate();
//! Do standard event & processing loop. Use threaded = true to separate event/updating loop from frame processing
void main_loop();
//! Process next frame
bool next_frame();
//! Change window title
void show_title();
//! translate RGB components into packed type
inline color_t get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const;
//! Get drawing memory descriptor
inline drawing_memory get_drawing_memory() const;
//! code of the ESCape key
static const int esc_key = 27;
//! Mouse events handler.
virtual void on_mouse(int x, int y, int key) {}
//! Mouse events handler.
virtual void on_key(int key) {}
//! Main processing loop. Redefine with your own
virtual void on_process() {
while (next_frame())
;
}
#ifdef _WINDOWS
//! Windows specific members
//! if VIDEO_WINMAIN isn't defined then set this just before init() by arguments of WinMain
static HINSTANCE win_hInstance;
static int win_iCmdShow;
//! optionally call it just before init() to set own. Use ascii strings convention
void win_set_class(WNDCLASSEX &);
//! load and set accelerator table from resources
void win_load_accelerators(int idc);
#endif
};
//! Drawing class
class drawing_area {
const std::size_t base_index, max_index, index_stride;
const depth_t pixel_depth;
unsigned int *const ptr32;
std::size_t index;
public:
const int start_x, start_y, size_x, size_y;
//! constructors
drawing_area(int x, int y, int sizex, int sizey);
inline drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem);
//! destructor
inline ~drawing_area();
//! update the image
void update();
//! set current position. local_x could be bigger then size_x
inline void set_pos(int local_x, int local_y);
//! put pixel in current position with incremental address calculating to next right pixel
inline void put_pixel(color_t color);
//! draw pixel at position by packed color
void set_pixel(int localx, int localy, color_t color) {
set_pos(localx, localy);
put_pixel(color);
}
};
extern int g_sizex;
extern int g_sizey;
extern unsigned int *g_pImg;
inline drawing_memory video::get_drawing_memory() const {
drawing_memory dmem;
dmem.pixel_depth = depth;
dmem.my_address = reinterpret_cast<uintptr_t>(g_pImg);
dmem.sizex = g_sizex;
dmem.sizey = g_sizey;
return dmem;
}
inline color_t video::get_color(colorcomp_t red, colorcomp_t green, colorcomp_t blue) const {
if (red_shift == 16) // only for depth == 24 && red_shift > blue_shift
return (red << 16) | (green << 8) | blue;
else if (depth >= 24)
return
#if __ANDROID__
// Setting Alpha to 0xFF
0xFF000000 |
#endif
(red << red_shift) | (green << green_shift) | (blue << blue_shift);
else if (depth > 0) {
depth_t bs = blue_shift, rs = red_shift;
if (blue_shift < 0)
blue >>= -bs, bs = 0;
else /*red_shift < 0*/
red >>= -rs, rs = 0;
return ((red << rs) & red_mask) | ((green << green_shift) & green_mask) |
((blue << bs) & blue_mask);
}
else { // UYVY colorspace
unsigned y, u, v;
y = red * 77 + green * 150 + blue * 29; // sum(77+150+29=256) * max(=255): limit->2^16
u = (2048 + (blue << 3) - (y >> 5)) >> 4; // (limit->2^12)>>4
v = (2048 + (red << 3) - (y >> 5)) >> 4;
y = y >> 8;
return u | (y << 8) | (v << 16) | (y << 24);
}
}
inline drawing_area::drawing_area(int x, int y, int sizex, int sizey, const drawing_memory &dmem)
: base_index(y * dmem.sizex + x),
max_index(dmem.sizex * dmem.sizey),
index_stride(dmem.sizex),
pixel_depth(dmem.pixel_depth),
ptr32(reinterpret_cast<unsigned int *>(dmem.my_address)),
start_x(x),
start_y(y),
size_x(sizex),
size_y(sizey) {
assert(x < dmem.sizex);
assert(y < dmem.sizey);
assert(x + sizex <= dmem.sizex);
assert(y + sizey <= dmem.sizey);
index = base_index; // current index
}
inline void drawing_area::set_pos(int local_x, int local_y) {
index = base_index + local_x + local_y * index_stride;
}
inline void drawing_area::put_pixel(color_t color) {
assert(index < max_index);
if (pixel_depth > 16)
ptr32[index++] = color;
else if (pixel_depth > 0)
((unsigned short *)ptr32)[index++] = (unsigned short)color;
else { // UYVY colorspace
if (index & 1)
color >>= 16;
((unsigned short *)ptr32)[index++] = (unsigned short)color;
}
}
inline drawing_area::~drawing_area() {}
#if defined(_WINDOWS) && (defined(VIDEO_WINMAIN) || defined(VIDEO_WINMAIN_ARGS))
#include <cstdlib>
//! define WinMain for subsystem:windows.
#ifdef VIDEO_WINMAIN_ARGS
int main(int, char *[]);
#else
int main();
#endif
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR szCmdLine, int iCmdShow) {
video::win_hInstance = hInstance;
video::win_iCmdShow = iCmdShow;
#ifdef VIDEO_WINMAIN_ARGS
return main(__argc, __argv);
#else
return main();
#endif
}
#endif
#endif /* TBB_examples_video_H */
+315
View File
@@ -0,0 +1,315 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/////// Common internal implementation of Windows-specific stuff //////////////
/////// Must be the first included header //////////////
#ifndef __WINVIDEO_H__
#define __WINVIDEO_H__
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
// Check that the target Windows version has all API calls required.
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#if _WIN32_WINNT < 0x0400
#define YIELD_TO_THREAD() Sleep(0)
#else
#define YIELD_TO_THREAD() SwitchToThread()
#endif
#include "video.hpp"
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
// maximum number of lines the output console should have
static const WORD MAX_CONSOLE_LINES = 500;
const COLORREF RGBKEY = RGB(8, 8, 16); // at least 8 for 16-bit palette
HWND g_hAppWnd; // The program's window handle
HANDLE g_handles[2] = { 0, 0 }; // thread and wake up event
unsigned int *g_pImg = 0; // drawing memory
int g_sizex, g_sizey;
static video *g_video = 0;
WNDPROC g_pUserProc = 0;
HINSTANCE video::win_hInstance = 0;
int video::win_iCmdShow = 0;
static WNDCLASSEX *gWndClass = 0;
static HACCEL hAccelTable = 0;
static DWORD g_msec = 0;
static int g_fps = 0, g_updates = 0, g_skips = 0;
bool DisplayError(LPSTR lpstrErr, HRESULT hres = 0); // always returns false
LRESULT CALLBACK InternalWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
//! Create window
bool WinInit(HINSTANCE hInstance,
int nCmdShow,
WNDCLASSEX *uwc,
const char *title,
bool fixedsize) {
WNDCLASSEX wndclass; // Our app's windows class
if (uwc) {
memcpy(&wndclass, uwc, sizeof(wndclass));
g_pUserProc = uwc->lpfnWndProc;
}
else {
memset(&wndclass, 0, sizeof(wndclass));
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.lpszClassName = title;
}
wndclass.cbSize = sizeof(wndclass);
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = InternalWndProc;
wndclass.style |= CS_HREDRAW | CS_VREDRAW;
wndclass.hbrBackground = CreateSolidBrush(RGBKEY);
if (!RegisterClassExA(&wndclass))
return false;
int xaddend = GetSystemMetrics(fixedsize ? SM_CXFIXEDFRAME : SM_CXFRAME) * 2;
int yaddend = GetSystemMetrics(fixedsize ? SM_CYFIXEDFRAME : SM_CYFRAME) * 2 +
GetSystemMetrics(SM_CYCAPTION);
if (wndclass.lpszMenuName)
yaddend += GetSystemMetrics(SM_CYMENU);
// Setup the new window's physical parameters - and tell Windows to create it
g_hAppWnd = CreateWindowA(wndclass.lpszClassName, // Window class name
title, // Window caption
!fixedsize ? WS_OVERLAPPEDWINDOW : // Window style
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, // Initial x pos: use default placement
0, // Initial y pos: not used here
g_sizex + xaddend, // Initial x size
g_sizey + yaddend, // Initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // Creation parameters
return g_hAppWnd != NULL;
}
//! create console window with redirection
static bool RedirectIOToConsole(void) {
int hConHandle;
size_t lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (size_t)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
if (hConHandle <= 0)
return false;
fp = _fdopen(hConHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
// redirect unbuffered STDERR to the console
lStdHandle = (size_t)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
if (hConHandle > 0) {
fp = _fdopen(hConHandle, "w");
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
}
// redirect unbuffered STDIN to the console
lStdHandle = (size_t)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
if (hConHandle > 0) {
fp = _fdopen(hConHandle, "r");
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
}
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
std::ios::sync_with_stdio();
return true;
}
video::video()
: depth(24),
red_shift(16),
green_shift(8),
blue_shift(0),
red_mask(0xff0000),
green_mask(0xff00),
blue_mask(0xff) {
assert(g_video == 0);
g_video = this;
title = "Video";
running = threaded = calc_fps = false;
updating = true;
}
//! optionally call it just before init() to set own
void video::win_set_class(WNDCLASSEX &wcex) {
gWndClass = &wcex;
}
void video::win_load_accelerators(int idc) {
hAccelTable = LoadAccelerators(win_hInstance, MAKEINTRESOURCE(idc));
}
bool video::init_console() {
if (RedirectIOToConsole()) {
if (!g_pImg && g_sizex && g_sizey)
g_pImg = new unsigned int[g_sizex * g_sizey];
if (g_pImg)
running = true;
return true;
}
return false;
}
video::~video() {
if (g_video)
terminate();
}
DWORD WINAPI thread_video(LPVOID lpParameter) {
video *v = (video *)lpParameter;
v->on_process();
return 0;
}
static bool loop_once(video *v) {
// screen update notify
if (int updates = g_updates) {
g_updates = 0;
if (g_video->updating) {
g_skips += updates - 1;
g_fps++;
}
else
g_skips += updates;
UpdateWindow(g_hAppWnd);
}
// update fps
DWORD msec = GetTickCount();
if (v->calc_fps && msec >= g_msec + 1000) {
double sec = (msec - g_msec) / 1000.0;
char buffer[256],
n = _snprintf(buffer, 128, "%s: %d fps", v->title, int(double(g_fps + g_skips) / sec));
if (g_skips)
_snprintf(buffer + n,
128,
" - %d skipped = %d updates",
int(g_skips / sec),
int(g_fps / sec));
SetWindowTextA(g_hAppWnd, buffer);
g_msec = msec;
g_skips = g_fps = 0;
}
// event processing, including painting
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
v->running = false;
return false;
}
if (!hAccelTable || !TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return true; // try again
}
return false;
}
//! Do standard event loop
void video::main_loop() {
// let Windows draw and unroll the window
InvalidateRect(g_hAppWnd, 0, false);
g_msec = GetTickCount(); // let's stay for 0,5 sec
while (g_msec + 500 > GetTickCount()) {
loop_once(this);
Sleep(1);
}
g_msec = GetTickCount();
// now, start main process
if (threaded) {
g_handles[0] = CreateThread(NULL, // LPSECURITY_ATTRIBUTES security_attrs
0, // SIZE_T stacksize
(LPTHREAD_START_ROUTINE)thread_video,
this, // argument
0,
0);
if (!g_handles[0]) {
DisplayError("Can't create thread");
return;
}
else // harmless race is possible here
g_handles[1] = CreateEvent(NULL, false, false, NULL);
while (running) {
while (loop_once(this))
;
YIELD_TO_THREAD(); // give time for processing when running on single CPU
DWORD r = MsgWaitForMultipleObjects(
2, g_handles, false, INFINITE, QS_ALLINPUT ^ QS_MOUSEMOVE);
if (r == WAIT_OBJECT_0)
break; // thread terminated
}
running = false;
if (WaitForSingleObject(g_handles[0], 3000) == WAIT_TIMEOUT) {
// there was not enough time for graceful shutdown, killing the example with code 1.
exit(1);
}
if (g_handles[0])
CloseHandle(g_handles[0]);
if (g_handles[1])
CloseHandle(g_handles[1]);
g_handles[0] = g_handles[1] = 0;
}
else
on_process();
}
//! Refresh screen picture
bool video::next_frame() {
if (!running)
return false;
g_updates++; // Fast but inaccurate counter. The data race here is benign.
if (!threaded)
while (loop_once(this))
;
else if (g_handles[1]) {
SetEvent(g_handles[1]);
YIELD_TO_THREAD();
}
return true;
}
//! Change window title
void video::show_title() {
if (g_hAppWnd)
SetWindowTextA(g_hAppWnd, title);
}
#endif //__WINVIDEO_H__
@@ -0,0 +1,56 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <Foundation/Foundation.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#import "OpenGLES/ES2/gl.h"
@interface OpenGLView : UIView {
NSTimer *timer;
CGRect imageRect;
}
@property (nonatomic, retain) NSTimer *timer;
@property (nonatomic) CGRect imageRect;
- (void) drawRect:(CGRect)rect;
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end
#elif TARGET_OS_MAC
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
@interface OpenGLView : NSOpenGLView{
NSTimer *timer;
}
@property (nonatomic,retain) NSTimer *timer;
- (void) drawRect:(NSRect)start;
- (void) mouseDown:(NSEvent *)theEvent;
- (void) keyDown:(NSEvent *)theEvent;
- (BOOL) acceptsFirstResponder;
- (void) viewDidEndLiveResize;
@end
#endif
@@ -0,0 +1,143 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "OpenGLView.h"
// defined in macvideo.cpp
extern char* window_title;
extern int cocoa_update;
extern int g_sizex, g_sizey;
extern unsigned int *g_pImg;
void on_mouse_func(int x, int y, int k);
void on_key_func(int x);
bool initialized = false;
#if TARGET_OS_IPHONE
#import "OpenGLES/ES2/gl.h"
@implementation OpenGLView
@synthesize timer;
@synthesize imageRect;
- (void)drawRect:(CGRect)start
{
if (initialized == false) {
NSLog(@"INITIALIZE");
timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(update_window) userInfo:nil repeats:YES];
imageRect = [[UIScreen mainScreen] bounds];
CGFloat full_height = imageRect.size.height;
const float ratio=(float)g_sizex/g_sizey;
imageRect.size.height=imageRect.size.width/ratio;
imageRect.origin.y=(full_height-imageRect.size.height)/2;
initialized = true;
}
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, g_pImg, 4*g_sizex*g_sizey, NULL);
CGImageRef inputImage = CGImageCreate(g_sizex, g_sizey, 8, 32, g_sizex * 4, colourSpace,(CGBitmapInfo)kCGImageAlphaNoneSkipLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);
UIImage *image = [UIImage imageWithCGImage:inputImage];
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colourSpace);
CGImageRelease(inputImage);
[image drawInRect:imageRect];
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint point = [[touches anyObject] locationInView:self];
const int x = point.x;
const int y = point.y;
if ( (y-imageRect.origin.y) > 0 && y < (imageRect.origin.y + imageRect.size.height ))
on_mouse_func( x*g_sizex/(imageRect.size.width), (y-imageRect.origin.y)*g_sizey/imageRect.size.height,1);
[self setNeedsDisplay];
}
-(void) update_window{
if( cocoa_update ) [self setNeedsDisplay];
}
@end
#elif TARGET_OS_MAC
#import <OpenGL/gl.h>
@implementation OpenGLView
@synthesize timer;
- (void) drawRect:(NSRect)start
{
if (initialized == false) {
NSLog(@"INITIALIZE");
timer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(update_window) userInfo:nil repeats:YES];
initialized = true;
}
glWindowPos2i(0, (int)self.visibleRect.size.height);
glPixelZoom( (float)self.visibleRect.size.width /(float)g_sizex,
-(float)self.visibleRect.size.height/(float)g_sizey);
glDrawPixels(g_sizex, g_sizey, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, g_pImg);
glFlush();
}
-(void) update_window{
if( cocoa_update ) [self setNeedsDisplay:YES];
if( window_title ) [self.window setTitle:[NSString stringWithFormat:@"%s", window_title]];
}
-(void) keyDown:(NSEvent *)theEvent{
on_key_func([theEvent.characters characterAtIndex:0]);
}
-(void) mouseDown:(NSEvent *)theEvent{
// mouse event for seismic and fractal
NSPoint point= theEvent.locationInWindow;
const int x = (int)point.x;
const int y = (int)point.y;
NSRect rect = self.visibleRect;
on_mouse_func(x*g_sizex/(int)rect.size.width,((int)rect.size.height-y)*g_sizey/(int)rect.size.height,1);
[self setNeedsDisplay:YES];
}
- (BOOL) acceptsFirstResponder
{
return YES;
}
- (void) rightMouseDown:(NSEvent *)theEvent
{
return;
}
-(void) viewDidEndLiveResize
{
NSRect rect = self.visibleRect;
const int x=(int)rect.size.width;
const int y=(int)rect.size.height;
[self.window setTitle:[NSString stringWithFormat:@"X=%d Y=%d", x,y]];
}
@end
#endif
@@ -0,0 +1 @@
APPL????
@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */
Binary file not shown.
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9060"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="494" id="495"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="tbbExample" id="56">
<menu key="submenu" title="tbbExample" systemMenu="apple" id="57">
<items>
<menuItem title="Quit tbbExample" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="tbbExample" allowsToolTipsWhenApplicationIsInactive="NO" deferred="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="100" y="100" width="480" height="360"/>
<rect key="screenRect" x="0.0" y="0.0" width="1280" height="1002"/>
<view key="contentView" focusRingType="none" horizontalHuggingPriority="1" verticalHuggingPriority="9" horizontalCompressionResistancePriority="1" verticalCompressionResistancePriority="1" id="372" customClass="OpenGLView">
<rect key="frame" x="0.0" y="0.0" width="480" height="360"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
</view>
</window>
<customObject id="494" customClass="tbbAppDelegate">
<connections>
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="AKo-RD-jUr">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="aF8-QV-POo">
<objects>
<viewController id="AKo-RD-jUr" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="SEe-ff-xUc"/>
<viewControllerLayoutGuide type="bottom" id="Cp9-IV-SKb"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="1aY-my-944" customClass="OpenGLView">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="wcZ-9q-FxX" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="90" y="88"/>
</scene>
</scenes>
</document>
@@ -0,0 +1,47 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <Availability.h>
#import <Foundation/Foundation.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
#import "tbbAppDelegate.h"
void get_screen_resolution(int *x, int *y) {
// Getting landscape screen resolution in any case
CGRect imageRect = [[UIScreen mainScreen] bounds];
*x=imageRect.size.width>imageRect.size.height?imageRect.size.width:imageRect.size.height;
*y=imageRect.size.width<imageRect.size.height?imageRect.size.width:imageRect.size.height;
return;
}
int cocoa_main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([tbbAppDelegate class]));
}
}
#elif TARGET_OS_MAC
#import <Cocoa/Cocoa.h>
int cocoa_main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **)argv);
}
#endif
@@ -0,0 +1,47 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
//
// Created by Xcode* 4.3.2
//
#import <Foundation/Foundation.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIKit.h>
@interface tbbAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
#elif TARGET_OS_MAC
#import <Cocoa/Cocoa.h>
@interface tbbAppDelegate : NSObject <NSApplicationDelegate>{
__unsafe_unretained NSWindow *_window;
}
@property (assign) IBOutlet NSWindow *window;
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender;
@end
#endif
@@ -0,0 +1,62 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "tbbAppDelegate.h"
#if TARGET_OS_IPHONE
@implementation tbbAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
exit(EXIT_SUCCESS);
}
@end
#elif TARGET_OS_MAC
@implementation tbbAppDelegate
@synthesize window = _window;
//declared in macvideo.cpp file
extern int g_sizex, g_sizey;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSRect windowSize;
windowSize.size.height = g_sizey;
windowSize.size.width = g_sizex;
windowSize.origin=_window.frame.origin;
[_window setFrame:windowSize display:YES];
}
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender
{
return YES;
}
@end
#endif
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>iOS</string>
<key>UIMainStoryboardFile</key>
<string>iOS</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string></string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.business</string>
<key>LSEnvironment</key>
<dict>
<key>DYLD_LIBRARY_PATH</key>
<string>Resources:.:../Resources:/tmp:$DYLD_LIBRARY_PATH</string>
<key>LIBRARY_PATH</key>
<string>Resources:.:../:/tmp:$DYLD_LIBRARY_PATH</string>
</dict>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2005-2021 Intel Corporation. All Rights Reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
+468
View File
@@ -0,0 +1,468 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Uncomment next line to disable shared memory features if you do not have libXext
// (http://www.xfree86.org/current/mit-shm.html)
//#define X_NOSHMEM
// Note that it may happen that the build environment supports the shared-memory extension
// (so there's no build-time reason to disable the relevant code by defining X_NOSHMEM),
// but that using shared memory still fails at run time.
// This situation will (ultimately) cause the error handler set by XSetErrorHandler()
// to be invoked with XErrorEvent::minor_code==X_ShmAttach. The code below tries to make
// such a determination at XShmAttach() time, which seems plausible, but unfortunately
// it has also been observed in a specific environment that the error may be reported
// at a later time instead, even after video::init_window() has returned.
// It is not clear whether this may happen in that way in any environment where it might
// depend on the kind of display, e.g., local vs. over "ssh -X", so #define'ing X_NOSHMEM
// may not always be the appropriate solution, therefore an environment variable
// has been introduced to disable shared memory at run time.
// A diagnostic has been added to advise the user about possible workarounds.
// X_ShmAttach macro was changed to 1 due to recent changes to X11/extensions/XShm.h header.
#include "video.hpp"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <sys/time.h>
#include <signal.h>
#include <pthread.h>
#ifndef X_NOSHMEM
#include <errno.h>
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
static XShmSegmentInfo shmseginfo;
static Pixmap pixmap = 0;
static bool already_called_X_ShmAttach = false;
static bool already_advised_about_NOSHMEM_workarounds = false;
#endif
static char *display_name = NULL;
static Display *dpy = NULL;
static Screen *scrn;
static Visual *vis;
static Colormap cmap;
static GC gc;
static Window win, rootW;
static int dispdepth = 0;
static XGCValues xgcv;
static XImage *ximage;
static int x_error = 0;
static int vidtype = 3;
int g_sizex, g_sizey;
static video *g_video = 0;
unsigned int *g_pImg = 0;
static int g_fps = 0;
struct timeval g_time;
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
Atom _XA_WM_DELETE_WINDOW = 0; // like in Xatom.h
///////////////////////////////////////////// public methods of video class ///////////////////////
video::video() {
assert(g_video == 0);
g_video = this;
title = "Video";
calc_fps = running = false;
updating = true;
}
inline void mask2bits(unsigned int mask, unsigned int &save, depth_t &shift) {
save = mask;
if (!mask) {
shift = dispdepth / 3;
return;
}
shift = 0;
while (!(mask & 1))
++shift, mask >>= 1;
int bits = 0;
while (mask & 1)
++bits, mask >>= 1;
shift += bits - 8;
}
int xerr_handler(Display *dpy_, XErrorEvent *error) {
x_error = error->error_code;
if (g_video)
g_video->running = false;
#ifndef X_NOSHMEM
if (error->minor_code == 1 /*X_ShmAttach*/ && already_called_X_ShmAttach &&
!already_advised_about_NOSHMEM_workarounds) {
char err[256];
XGetErrorText(dpy_, x_error, err, 255);
fprintf(stderr, "Warning: Can't attach shared memory to display: %s (%d)\n", err, x_error);
fprintf(
stderr,
"If you are seeing a black output window, сheck if you have installed Xext library and rebuild project");
already_advised_about_NOSHMEM_workarounds = true;
}
#else
(void)dpy_; // warning prevention
#endif
return 0;
}
bool video::init_window(int xsize, int ysize) {
{ //enclose local variables before fail label
g_sizex = xsize;
g_sizey = ysize;
// Open the display
if (!dpy) {
dpy = XOpenDisplay(display_name);
if (!dpy) {
fprintf(stderr, "Can't open X11 display %s\n", XDisplayName(display_name));
goto fail;
}
}
int theScreen = DefaultScreen(dpy);
scrn = ScreenOfDisplay(dpy, theScreen);
dispdepth = DefaultDepth(dpy, theScreen);
XVisualInfo vinfo;
if (!((dispdepth >= 15 && dispdepth <= 32 &&
XMatchVisualInfo(dpy, theScreen, dispdepth, TrueColor, &vinfo)) ||
XMatchVisualInfo(dpy, theScreen, 24, TrueColor, &vinfo) ||
XMatchVisualInfo(dpy, theScreen, 32, TrueColor, &vinfo) ||
XMatchVisualInfo(dpy, theScreen, 16, TrueColor, &vinfo) ||
XMatchVisualInfo(dpy, theScreen, 15, TrueColor, &vinfo))) {
fprintf(stderr, "Display has no appropriate True Color visual\n");
goto fail;
}
vis = vinfo.visual;
depth = dispdepth = vinfo.depth;
mask2bits(vinfo.red_mask, red_mask, red_shift);
mask2bits(vinfo.green_mask, green_mask, green_shift);
mask2bits(vinfo.blue_mask, blue_mask, blue_shift);
rootW = RootWindow(dpy, theScreen);
cmap = XCreateColormap(dpy, rootW, vis, AllocNone);
XSetWindowAttributes attrs;
attrs.backing_store = Always;
attrs.colormap = cmap;
attrs.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask;
attrs.background_pixel = BlackPixelOfScreen(scrn);
attrs.border_pixel = WhitePixelOfScreen(scrn);
win = XCreateWindow(dpy,
rootW,
0,
0,
xsize,
ysize,
2,
dispdepth,
InputOutput,
vis,
CWBackingStore | CWColormap | CWEventMask | CWBackPixel | CWBorderPixel,
&attrs);
if (!win) {
fprintf(stderr, "Can't create the window\n");
goto fail;
}
XSizeHints sh;
sh.flags = PSize | PMinSize | PMaxSize;
sh.width = sh.min_width = sh.max_width = xsize;
sh.height = sh.min_height = sh.max_height = ysize;
XSetStandardProperties(dpy, win, g_video->title, g_video->title, None, NULL, 0, &sh);
_XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", false);
XSetWMProtocols(dpy, win, &_XA_WM_DELETE_WINDOW, 1);
gc = XCreateGC(dpy, win, 0L, &xgcv);
XMapRaised(dpy, win);
XFlush(dpy);
#ifdef X_FULLSYNC
XSynchronize(dpy, true);
#endif
XSetErrorHandler(xerr_handler);
int imgbytes = xsize * ysize * (dispdepth <= 16 ? 2 : 4);
const char *vidstr;
#ifndef X_NOSHMEM
int major, minor, pixmaps;
if (XShmQueryExtension(dpy) &&
XShmQueryVersion(dpy, &major, &minor, &pixmaps)) { // Shared memory
shmseginfo.shmid = shmget(IPC_PRIVATE, imgbytes, IPC_CREAT | 0777);
if (shmseginfo.shmid < 0) {
fprintf(stderr, "Warning: Can't get shared memory: %s\n", strerror(errno));
goto generic;
}
g_pImg = (unsigned int *)(shmseginfo.shmaddr = (char *)shmat(shmseginfo.shmid, 0, 0));
if (g_pImg == (unsigned int *)-1) {
fprintf(stderr, "Warning: Can't attach to shared memory: %s\n", strerror(errno));
shmctl(shmseginfo.shmid, IPC_RMID, NULL);
goto generic;
}
shmseginfo.readOnly = false;
if (!XShmAttach(dpy, &shmseginfo) || x_error) {
char err[256];
XGetErrorText(dpy, x_error, err, 255);
fprintf(stderr,
"Warning: Can't attach shared memory to display: %s (%d)\n",
err,
x_error);
shmdt(shmseginfo.shmaddr);
shmctl(shmseginfo.shmid, IPC_RMID, NULL);
goto generic;
}
already_called_X_ShmAttach = true;
#ifndef X_NOSHMPIX
if (pixmaps && XShmPixmapFormat(dpy) == ZPixmap) { // Pixmaps
vidtype = 2;
vidstr = "X11 shared memory pixmap";
pixmap = XShmCreatePixmap(
dpy, win, (char *)g_pImg, &shmseginfo, xsize, ysize, dispdepth);
XSetWindowBackgroundPixmap(dpy, win, pixmap);
}
else
#endif //!X_NOSHMPIX
{ // Standard
vidtype = 1;
vidstr = "X11 shared memory";
ximage =
XShmCreateImage(dpy, vis, dispdepth, ZPixmap, 0, &shmseginfo, xsize, ysize);
if (!ximage) {
fprintf(stderr, "Can't create the shared image\n");
goto fail;
}
assert(ximage->bytes_per_line == xsize * (dispdepth <= 16 ? 2 : 4));
ximage->data = shmseginfo.shmaddr;
}
}
else
#endif
{
#ifndef X_NOSHMEM
generic:
#endif
vidtype = 0;
vidstr = "generic X11";
g_pImg = new unsigned int[imgbytes / sizeof(int)];
ximage = XCreateImage(dpy,
vis,
dispdepth,
ZPixmap,
0,
(char *)g_pImg,
xsize,
ysize,
32,
imgbytes / ysize);
if (!ximage) {
fprintf(stderr, "Can't create the image\n");
goto fail;
}
}
if (ximage) {
// Note: It may be more efficient to adopt the server's byte order
// and swap once per get_color() call instead of once per pixel.
const uint32_t probe = 0x03020100;
const bool big_endian = (((const char *)(&probe))[0] == 0x03);
ximage->byte_order = big_endian ? MSBFirst : LSBFirst;
}
printf("Note: using %s with %s visual for %d-bit color depth\n",
vidstr,
vis == DefaultVisual(dpy, theScreen) ? "default" : "non-default",
dispdepth);
running = true;
return true;
} // end of enclosing local variables
fail:
terminate();
init_console();
return false;
}
bool video::init_console() {
if (!g_pImg && g_sizex && g_sizey) {
dispdepth = 24;
red_shift = 16;
vidtype = 3; // fake video
g_pImg = new unsigned int[g_sizex * g_sizey];
running = true;
}
return true;
}
void video::terminate() {
running = false;
if (dpy) {
vidtype = 3; // stop video
if (threaded) {
pthread_mutex_lock(&g_mutex);
pthread_mutex_unlock(&g_mutex);
}
if (ximage) {
XDestroyImage(ximage);
ximage = 0;
g_pImg = 0;
} // it frees g_pImg for vidtype == 0
#ifndef X_NOSHMEM
if (pixmap)
XFreePixmap(dpy, pixmap);
if (shmseginfo.shmaddr) {
XShmDetach(dpy, &shmseginfo);
shmdt(shmseginfo.shmaddr);
g_pImg = 0;
}
if (shmseginfo.shmid >= 0)
shmctl(shmseginfo.shmid, IPC_RMID, NULL);
#endif
if (gc)
XFreeGC(dpy, gc);
if (win)
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
dpy = 0;
}
if (g_pImg) {
delete[] g_pImg;
g_pImg = 0;
} // if was allocated for console mode
}
video::~video() {
if (g_video)
terminate();
g_video = 0;
}
//! Do standard event loop
void video::main_loop() {
struct timezone tz;
gettimeofday(&g_time, &tz);
on_process();
}
//! Check for pending events once
bool video::next_frame() {
if (!running)
return false;
//! try acquire mutex if threaded code, returns on failure
if (vidtype == 3 || threaded && pthread_mutex_trylock(&g_mutex))
return running;
//! Refresh screen picture
g_fps++;
#ifndef X_NOSHMPIX
if (vidtype == 2 && updating)
XClearWindow(dpy, win);
#endif
while (XPending(dpy)) {
XEvent report;
XNextEvent(dpy, &report);
switch (report.type) {
case ClientMessage:
if (report.xclient.format != 32 || report.xclient.data.l[0] != _XA_WM_DELETE_WINDOW)
break;
case DestroyNotify: running = false;
case KeyPress: on_key(XLookupKeysym(&report.xkey, 0)); break;
case ButtonPress:
on_mouse(report.xbutton.x, report.xbutton.y, report.xbutton.button);
break;
case ButtonRelease:
on_mouse(report.xbutton.x, report.xbutton.y, -report.xbutton.button);
break;
}
}
struct timezone tz;
struct timeval now_time;
gettimeofday(&now_time, &tz);
double sec = (now_time.tv_sec + 1.0 * now_time.tv_usec / 1000000.0) -
(g_time.tv_sec + 1.0 * g_time.tv_usec / 1000000.0);
if (sec > 1) {
memcpy(&g_time, &now_time, sizeof(g_time));
if (calc_fps) {
double fps = g_fps;
g_fps = 0;
char buffer[256];
snprintf(buffer,
256,
"%s%s: %d fps",
title,
updating ? "" : " (no updating)",
int(fps / sec));
XStoreName(dpy, win, buffer);
}
#ifndef X_FULLSYNC
XSync(dpy, false); // It is often better then using XSynchronize(dpy, true)
#endif //X_FULLSYNC
}
if (threaded)
pthread_mutex_unlock(&g_mutex);
return true;
}
//! Change window title
void video::show_title() {
if (vidtype < 3)
XStoreName(dpy, win, title);
}
drawing_area::drawing_area(int x, int y, int sizex, int sizey)
: base_index(y * g_sizex + x),
max_index(g_sizex * g_sizey),
index_stride(g_sizex),
pixel_depth(dispdepth),
ptr32(g_pImg),
start_x(x),
start_y(y),
size_x(sizex),
size_y(sizey) {
assert(x < g_sizex);
assert(y < g_sizey);
assert(x + sizex <= g_sizex);
assert(y + sizey <= g_sizey);
index = base_index; // current index
}
void drawing_area::update() {
if (!g_video->updating)
return;
#ifndef X_NOSHMEM
switch (vidtype) {
case 0:
#endif
pthread_mutex_lock(&g_mutex);
if (vidtype == 0)
XPutImage(dpy, win, gc, ximage, start_x, start_y, start_x, start_y, size_x, size_y);
pthread_mutex_unlock(&g_mutex);
#ifndef X_NOSHMEM
break;
case 1:
pthread_mutex_lock(&g_mutex);
if (vidtype == 1)
XShmPutImage(dpy,
win,
gc,
ximage,
start_x,
start_y,
start_x,
start_y,
size_x,
size_y,
false);
pthread_mutex_unlock(&g_mutex);
break;
/*case 2: make it in next_frame(); break;*/
}
#endif
}
+74
View File
@@ -0,0 +1,74 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef TBB_examples_fast_random_H
#define TBB_examples_fast_random_H
#include <cstddef>
namespace utility {
//------------------------------------------------------------------------
// FastRandom
//------------------------------------------------------------------------
namespace internal {
std::size_t GetPrime(std::size_t seed);
}
//! A fast random number generator.
/** Uses linear congruential method. */
class FastRandom {
std::size_t x, a;
public:
//! Get a random number.
unsigned short get() {
return get(x);
}
//! Get a random number for the given seed; update the seed for next use.
unsigned short get(std::size_t& seed) {
unsigned short r = (unsigned short)(seed >> 16);
seed = seed * a + 1;
return r;
}
//! Construct a random number generator.
FastRandom(std::size_t seed) {
x = seed * internal::GetPrime(seed);
a = internal::GetPrime(x);
}
};
} // namespace utility
namespace utility {
namespace internal {
//! Table of primes used by fast random-number generator (FastRandom).
static const unsigned Primes[] = {
0x9e3779b1, 0xffe6cc59, 0x2109f6dd, 0x43977ab5, 0xba5703f5, 0xb495a877, 0xe1626741, 0x79695e6b,
0xbc98c09f, 0xd5bee2b3, 0x287488f9, 0x3af18231, 0x9677cd4d, 0xbe3a6929, 0xadc6a877, 0xdcf0674b,
0xbe4d6fe9, 0x5f15e201, 0x99afc3fd, 0xf3f16801, 0xe222cfff, 0x24ba5fdb, 0x0620452d, 0x79f149e3,
0xc8b93f49, 0x972702cd, 0xb07dd827, 0x6c97d5ed, 0x085a3d61, 0x46eb5ea7, 0x3d9910ed, 0x2e687b5b,
0x29609227, 0x6eb081f1, 0x0954c4e1, 0x9d114db9, 0x542acfa9, 0xb3e6bd7b, 0x0742d917, 0xe9f3ffa7,
0x54581edb, 0xf2480f45, 0x0bb9288f, 0xef1affc7, 0x85fa0ca7, 0x3ccc14db, 0xe6baf34b, 0x343377f7,
0x5ca19031, 0xe6d9293b, 0xf0a9f391, 0x5d2e980b, 0xfc411073, 0xc3749363, 0xb892d829, 0x3549366b,
0x629750ad, 0xb98294e5, 0x892d9483, 0xc235baf3, 0x3d2402a3, 0x6bdef3c9, 0xbec333cd, 0x40c9520f
};
std::size_t GetPrime(std::size_t seed) {
return Primes[seed % (sizeof(Primes) / sizeof(Primes[0]))];
}
} // namespace internal
} // namespace utility
#endif /* TBB_examples_fast_random_H */
@@ -0,0 +1,28 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef TBB_examples_num_threads_H
#define TBB_examples_num_threads_H
#include "oneapi/tbb/task_arena.h"
namespace utility {
inline int get_default_num_threads() {
return oneapi::tbb::this_task_arena::max_concurrency();
}
} // namespace utility
#endif /* TBB_examples_num_threads_H */
+575
View File
@@ -0,0 +1,575 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef TBB_examples_utility_H
#define TBB_examples_utility_H
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <utility>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <sstream>
#include <numeric>
#include <stdexcept>
#include <memory>
#include <iostream>
// TBB headers should not be used, as some examples may need to be built without TBB.
namespace utility {
namespace internal {
//TODO: add tcs
template <class dest_type>
dest_type& string_to(std::string const& s, dest_type& result) {
std::stringstream stream(s);
stream >> result;
if ((!stream) || (stream.fail())) {
throw std::invalid_argument("error converting string '" + std::string(s) + "'");
}
return result;
}
template <class dest_type>
dest_type string_to(std::string const& s) {
dest_type result;
return string_to(s, result);
}
template <typename>
struct is_bool {
static bool value() {
return false;
}
};
template <>
struct is_bool<bool> {
static bool value() {
return true;
}
};
class type_base {
type_base& operator=(const type_base&);
public:
const std::string name;
const std::string description;
type_base(std::string a_name, std::string a_description)
: name(a_name),
description(a_description) {}
virtual void parse_and_store(const std::string& s) = 0;
virtual std::string value() const = 0;
virtual std::unique_ptr<type_base> clone() const = 0;
virtual ~type_base() {}
};
template <typename type>
class type_impl : public type_base {
private:
type_impl(const type_impl& src)
: type_base(src.name, src.description),
target(src.target),
validating_function(src.validating_function) {}
type_impl& operator=(const type_impl&);
typedef bool (*validating_function_type)(const type&);
type& target;
validating_function_type validating_function;
public:
type_impl(std::string a_name,
std::string a_description,
type& a_target,
validating_function_type a_validating_function = nullptr)
: type_base(a_name, a_description),
target(a_target),
validating_function(a_validating_function){};
void parse_and_store(const std::string& s) /*override*/ {
try {
const bool is_bool = internal::is_bool<type>::value();
if (is_bool && s.empty()) {
//to avoid directly assigning true
//(as it will impose additional layer of indirection)
//so, simply pass it as string
internal::string_to("1", target);
}
else {
internal::string_to(s, target);
}
}
catch (std::invalid_argument& e) {
std::stringstream str;
str << "'" << s << "' is incorrect input for argument '" << name << "'"
<< " (" << e.what() << ")";
throw std::invalid_argument(str.str());
}
if (validating_function) {
if (!((validating_function)(target))) {
std::stringstream str;
str << "'" << target << "' is invalid value for argument '" << name << "'";
throw std::invalid_argument(str.str());
}
}
}
template <typename t>
static bool is_null_c_str(t&) {
return false;
}
static bool is_null_c_str(char* s) {
return s == nullptr;
}
std::string value() const /*override*/ {
std::stringstream str;
if (!is_null_c_str(target))
str << target;
return str.str();
}
std::unique_ptr<type_base> clone() const /*override*/ {
return std::unique_ptr<type_base>(new type_impl(*this));
}
};
class argument {
private:
std::unique_ptr<type_base> p_type;
bool matched_;
public:
argument(argument const& other)
: p_type(other.p_type.get() ? (other.p_type->clone()).release() : nullptr),
matched_(other.matched_) {}
argument& operator=(argument a) {
this->swap(a);
return *this;
}
void swap(argument& other) {
std::swap(p_type, other.p_type);
std::swap(matched_, other.matched_);
}
template <class type>
argument(std::string a_name,
std::string a_description,
type& dest,
bool (*a_validating_function)(const type&) = nullptr)
: p_type(new type_impl<type>(a_name, a_description, dest, a_validating_function)),
matched_(false) {}
std::string value() const {
return p_type->value();
}
std::string name() const {
return p_type->name;
}
std::string description() const {
return p_type->description;
}
void parse_and_store(const std::string& s) {
p_type->parse_and_store(s);
matched_ = true;
}
bool is_matched() const {
return matched_;
}
};
} // namespace internal
class cli_argument_pack {
typedef std::map<std::string, internal::argument> args_map_type;
typedef std::vector<std::string> args_display_order_type;
typedef std::vector<std::string> positional_arg_names_type;
private:
args_map_type args_map;
args_display_order_type args_display_order;
positional_arg_names_type positional_arg_names;
std::set<std::string> bool_args_names;
private:
void add_arg(internal::argument const& a) {
std::pair<args_map_type::iterator, bool> result =
args_map.insert(std::make_pair(a.name(), a));
if (!result.second) {
throw std::invalid_argument("argument with name: '" + a.name() +
"' already registered");
}
args_display_order.push_back(a.name());
}
public:
template <typename type>
cli_argument_pack& arg(type& dest,
std::string const& name,
std::string const& description,
bool (*validate)(const type&) = nullptr) {
internal::argument a(name, description, dest, validate);
add_arg(a);
if (internal::is_bool<type>::value()) {
bool_args_names.insert(name);
}
return *this;
}
//Positional means that argument name can be omitted in actual CL
//only key to match values for parameters with
template <typename type>
cli_argument_pack& positional_arg(type& dest,
std::string const& name,
std::string const& description,
bool (*validate)(const type&) = nullptr) {
internal::argument a(name, description, dest, validate);
add_arg(a);
if (internal::is_bool<type>::value()) {
bool_args_names.insert(name);
}
positional_arg_names.push_back(name);
return *this;
}
void parse(std::size_t argc, char const* argv[]) {
{
std::size_t current_positional_index = 0;
for (std::size_t j = 1; j < argc; j++) {
internal::argument* pa = nullptr;
std::string argument_value;
const char* const begin = argv[j];
const char* const end = begin + std::strlen(argv[j]);
const char* const assign_sign = std::find(begin, end, '=');
struct throw_unknown_parameter {
static void _(std::string const& location) {
throw std::invalid_argument(std::string("unknown parameter starting at:'") +
location + "'");
}
};
//first try to interpret it like parameter=value string
if (assign_sign != end) {
std::string name_found = std::string(begin, assign_sign);
args_map_type::iterator it = args_map.find(name_found);
if (it != args_map.end()) {
pa = &((*it).second);
argument_value = std::string(assign_sign + 1, end);
}
else {
throw_unknown_parameter::_(argv[j]);
}
}
//then see is it a named flag
else {
args_map_type::iterator it = args_map.find(argv[j]);
if (it != args_map.end()) {
pa = &((*it).second);
argument_value = "";
}
//then try it as positional argument without name specified
else if (current_positional_index < positional_arg_names.size()) {
std::stringstream str(argv[j]);
args_map_type::iterator found_positional_arg =
args_map.find(positional_arg_names.at(current_positional_index));
//TODO: probably use of smarter assert would help here
assert(
found_positional_arg !=
args_map
.end() /*&&"positional_arg_names and args_map are out of sync"*/);
if (found_positional_arg == args_map.end()) {
throw std::logic_error(
"positional_arg_names and args_map are out of sync");
}
pa = &((*found_positional_arg).second);
argument_value = argv[j];
current_positional_index++;
}
else {
//TODO: add tc to check
throw_unknown_parameter::_(argv[j]);
}
}
assert(pa);
if (pa->is_matched()) {
throw std::invalid_argument(std::string("several values specified for: '") +
pa->name() + "' argument");
}
pa->parse_and_store(argument_value);
}
}
}
std::string usage_string(const std::string& binary_name) const {
std::string command_line_params;
std::string summary_description;
for (args_display_order_type::const_iterator it = args_display_order.begin();
it != args_display_order.end();
++it) {
const bool is_bool = (0 != bool_args_names.count((*it)));
args_map_type::const_iterator argument_it = args_map.find(*it);
//TODO: probably use of smarter assert would help here
assert(argument_it !=
args_map.end() /*&&"args_display_order and args_map are out of sync"*/);
if (argument_it == args_map.end()) {
throw std::logic_error("args_display_order and args_map are out of sync");
}
const internal::argument& a = (*argument_it).second;
command_line_params += " [" + a.name() + (is_bool ? "" : "=value") + "]";
summary_description +=
" " + a.name() + " - " + a.description() + " (" + a.value() + ")" + "\n";
}
std::string positional_arg_cl;
for (positional_arg_names_type::const_iterator it = positional_arg_names.begin();
it != positional_arg_names.end();
++it) {
positional_arg_cl += " [" + (*it);
}
for (std::size_t i = 0; i < positional_arg_names.size(); ++i) {
positional_arg_cl += "]";
}
command_line_params += positional_arg_cl;
std::stringstream str;
str << " Program usage is:"
<< "\n"
<< " " << binary_name << command_line_params << "\n"
<< "\n"
<< " where:"
<< "\n"
<< summary_description;
return str.str();
}
}; // class cli_argument_pack
namespace internal {
template <typename T>
bool is_power_of_2(T val) {
std::size_t intval = std::size_t(val);
return (intval & (intval - 1)) == std::size_t(0);
}
int step_function_plus(int previous, double step) {
return static_cast<int>(previous + step);
}
int step_function_multiply(int previous, double multiply) {
return static_cast<int>(previous * multiply);
}
// "Power-of-2 ladder": nsteps is the desired number of steps between any subsequent powers of 2.
// The actual step is the quotient of the nearest smaller power of 2 divided by that number (but at least 1).
// E.g., '1:32:#4' means 1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32
int step_function_power2_ladder(int previous, double nsteps) {
int steps = int(nsteps);
assert(is_power_of_2(steps)); // must be a power of 2
// The actual step is 1 until the value is twice as big as nsteps
if (previous < 2 * steps)
return previous + 1;
// calculate the previous power of 2
int prev_power2 = previous / 2; // start with half the given value
int rshift = 1; // and with the shift of 1;
while (int shifted =
prev_power2 >> rshift) { // shift the value right; while the result is non-zero,
prev_power2 |= shifted; // add the bits set in 'shifted';
rshift <<= 1; // double the shift, as twice as many top bits are set;
} // repeat.
++prev_power2; // all low bits set; now it's just one less than the desired power of 2
assert(is_power_of_2(prev_power2));
assert((prev_power2 <= previous) && (2 * prev_power2 > previous));
// The actual step value is the previous power of 2 divided by steps
return previous + (prev_power2 / steps);
}
typedef int (*step_function_ptr_type)(int, double);
struct step_function_descriptor {
char mnemonic;
step_function_ptr_type function;
public:
step_function_descriptor(char a_mnemonic, step_function_ptr_type a_function)
: mnemonic(a_mnemonic),
function(a_function) {}
private:
void operator=(step_function_descriptor const&);
};
step_function_descriptor step_function_descriptors[] = {
step_function_descriptor('*', step_function_multiply),
step_function_descriptor('+', step_function_plus),
step_function_descriptor('#', step_function_power2_ladder)
};
template <typename T, std::size_t N>
inline std::size_t array_length(const T (&)[N]) {
return N;
}
struct thread_range_step {
step_function_ptr_type step_function;
double step_function_argument;
thread_range_step(step_function_ptr_type step_function_, double step_function_argument_)
: step_function(step_function_),
step_function_argument(step_function_argument_) {
if (!step_function_)
throw std::invalid_argument(
"step_function for thread range step should not be nullptr");
}
int operator()(int previous) const {
assert(0 <= previous); // test 0<=first and loop discipline
const int ret = step_function(previous, step_function_argument);
assert(previous < ret);
return ret;
}
friend std::istream& operator>>(std::istream& input_stream, thread_range_step& step) {
char function_char;
double function_argument;
input_stream >> function_char >> function_argument;
std::size_t i = 0;
while ((i < array_length(step_function_descriptors)) &&
(step_function_descriptors[i].mnemonic != function_char))
++i;
if (i >= array_length(step_function_descriptors)) {
throw std::invalid_argument("unknown step function mnemonic: " +
std::string(1, function_char));
}
else if ((function_char == '#') && !is_power_of_2(function_argument)) {
throw std::invalid_argument("the argument of # should be a power of 2");
}
step.step_function = step_function_descriptors[i].function;
step.step_function_argument = function_argument;
return input_stream;
}
};
} // namespace internal
struct thread_number_range {
int (*auto_number_of_threads)();
int first; // 0<=first (0 can be used as a special value)
int last; // first<=last
::utility::internal::thread_range_step step;
thread_number_range(
int (*auto_number_of_threads_)(),
int low_ = 1,
int high_ = -1,
::utility::internal::thread_range_step step_ =
::utility::internal::thread_range_step(::utility::internal::step_function_power2_ladder,
4))
: auto_number_of_threads(auto_number_of_threads_),
first(low_),
last((high_ > -1) ? high_ : auto_number_of_threads_()),
step(step_) {
if (first < 0) {
throw std::invalid_argument("negative value not allowed");
}
if (first > last) {
throw std::invalid_argument("decreasing sequence not allowed");
}
}
friend std::istream& operator>>(std::istream& i, thread_number_range& range) {
try {
std::string s;
i >> s;
struct string_to_number_of_threads {
int auto_value;
string_to_number_of_threads(int auto_value_) : auto_value(auto_value_) {}
int operator()(const std::string& value) const {
return (value == "auto") ? auto_value : internal::string_to<int>(value);
}
};
string_to_number_of_threads string_to_number_of_threads(range.auto_number_of_threads());
int low, high;
std::size_t colon = s.find(':');
if (colon == std::string::npos) {
low = high = string_to_number_of_threads(s);
}
else {
//it is a range
std::size_t second_colon = s.find(':', colon + 1);
low = string_to_number_of_threads(std::string(s, 0, colon)); //not copying the colon
high = string_to_number_of_threads(
std::string(s, colon + 1, second_colon - (colon + 1))); //not copying the colons
if (second_colon != std::string::npos) {
internal::string_to(std::string(s, second_colon + 1), range.step);
}
}
range = thread_number_range(range.auto_number_of_threads, low, high, range.step);
}
catch (std::invalid_argument&) {
i.setstate(std::ios::failbit);
throw;
}
return i;
}
friend std::ostream& operator<<(std::ostream& o, thread_number_range const& range) {
using namespace internal;
std::size_t i = 0;
for (; i < array_length(step_function_descriptors) &&
step_function_descriptors[i].function != range.step.step_function;
++i) {
}
if (i >= array_length(step_function_descriptors)) {
throw std::invalid_argument("unknown step function for thread range");
}
o << range.first << ":" << range.last << ":" << step_function_descriptors[i].mnemonic
<< range.step.step_function_argument;
return o;
}
}; // struct thread_number_range
//TODO: fix unused warning here
static const char* thread_number_range_desc =
"number of threads to use; a range of the form low[:high[:(+|*|#)step]],"
"\n\twhere low and optional high are non-negative integers or 'auto' for the default choice,"
"\n\tand optional step expression specifies how thread numbers are chosen within the range.";
inline void report_elapsed_time(double seconds) {
std::cout << "elapsed time : " << seconds << " seconds"
<< "\n";
}
inline void report_skipped() {
std::cout << "skip"
<< "\n";
}
inline void parse_cli_arguments(int argc, const char* argv[], utility::cli_argument_pack cli_pack) {
bool show_help = false;
cli_pack.arg(show_help, "-h", "show this message");
bool invalid_input = false;
try {
cli_pack.parse(argc, argv);
}
catch (std::exception& e) {
std::cerr << "error occurred while parsing command line."
<< "\n"
<< "error text: " << e.what() << "\n"
<< std::flush;
invalid_input = true;
}
if (show_help || invalid_input) {
std::cout << cli_pack.usage_string(argv[0]) << std::flush;
std::exit(0);
}
}
inline void parse_cli_arguments(int argc, char* argv[], utility::cli_argument_pack cli_pack) {
parse_cli_arguments(argc, const_cast<const char**>(argv), cli_pack);
}
} // namespace utility
#endif /* TBB_examples_utility_H */
+6
View File
@@ -0,0 +1,6 @@
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
This directory contains examples of the `concurrent_hash_map` container.
| Code sample name | Description
|:--- |:---
| count_strings | Concurrently inserts strings into a `concurrent_hash_map` container.
@@ -0,0 +1,33 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(count_strings CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
add_executable(count_strings count_strings.cpp)
target_link_libraries(count_strings TBB::tbb Threads::Threads)
target_compile_options(count_strings PRIVATE ${TBB_CXX_STD_FLAG})
set(EXECUTABLE "$<TARGET_FILE:count_strings>")
set(ARGS "")
set(PERF_ARGS auto 10000000 silent)
add_execution_target(run_count_strings count_strings ${EXECUTABLE} "${ARGS}")
add_execution_target(perf_run_count_strings count_strings ${EXECUTABLE} "${PERF_ARGS}")
@@ -0,0 +1,24 @@
# Count_strings sample
The example counts the number of unique words in a text.
## Building the example
```
cmake <path_to_example>
cmake --build .
```
## Running the sample
### Predefined make targets
* `make run_count_strings` - executes the example with predefined parameters.
* `make perf_run_count_strings` - executes the example with suggested parameters to measure the oneTBB performance.
### Application parameters
Usage:
```
count_strings [n-of-threads=value] [n-of-strings=value] [verbose] [silent] [count_collisions] [-h] [n-of-threads [n-of-strings]]
```
* `-h` - prints the help for command line options.
* `n-of-threads` - number of threads to use; a range of the form low\[:high\], where low and optional high are non-negative integers or `auto` for a platform-specific default number.
* `n-of-strings` - number of strings.
* `verbose` - prints diagnostic output to screen.
* `silent` - no output except elapsed time.
@@ -0,0 +1,295 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cstdio>
#include <string>
// Apple clang and MSVC defines their own specializations for std::hash<std::basic_string<T, Traits, Alloc>>
#if !(_LIBCPP_VERSION) && !(_CPPLIB_VER)
namespace std {
template <typename CharT, typename Traits, typename Allocator>
class hash<std::basic_string<CharT, Traits, Allocator>> {
public:
std::size_t operator()(const std::basic_string<CharT, Traits, Allocator>& s) const {
std::size_t h = 0;
for (const CharT* c = s.c_str(); *c; ++c) {
h = h * hash_multiplier ^ char_hash(*c);
}
return h;
}
private:
static constexpr std::size_t hash_multiplier = (std::size_t)(
(sizeof(std::size_t) == sizeof(unsigned)) ? 2654435769U : 11400714819323198485ULL);
std::hash<CharT> char_hash;
}; // strunt hash<std::basic_string>
} // namespace std
#endif // !(_LIBCPP_VERSION || _CPPLIB_VER)
#include "oneapi/tbb/concurrent_hash_map.h"
#include "oneapi/tbb/blocked_range.h"
#include "oneapi/tbb/parallel_for.h"
#include "oneapi/tbb/tick_count.h"
#include "oneapi/tbb/tbb_allocator.h"
#include "oneapi/tbb/global_control.h"
#include "common/utility/utility.hpp"
#include "common/utility/get_default_num_threads.hpp"
#include <map>
//! Count collisions
std::map<std::size_t, int> hashes;
int c = 0;
//! String type
typedef std::basic_string<char, std::char_traits<char>, oneapi::tbb::tbb_allocator<char>> MyString;
//! Set to true to counts.
static bool verbose = false;
static bool silent = false;
static bool count_collisions = false;
//! Problem size
long N = 1000000;
const int size_factor = 2;
//! A concurrent hash table that maps strings to ints.
typedef oneapi::tbb::concurrent_hash_map<MyString, int> StringTable;
//! Function object for counting occurrences of strings.
struct Tally {
StringTable& table;
Tally(StringTable& table_) : table(table_) {}
void operator()(const oneapi::tbb::blocked_range<MyString*> range) const {
for (MyString* p = range.begin(); p != range.end(); ++p) {
StringTable::accessor a;
table.insert(a, *p);
a->second += 1;
}
}
};
static MyString* Data;
static void CountOccurrences(int nthreads) {
StringTable table;
oneapi::tbb::tick_count t0 = oneapi::tbb::tick_count::now();
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<MyString*>(Data, Data + N, 1000),
Tally(table));
oneapi::tbb::tick_count t1 = oneapi::tbb::tick_count::now();
int n = 0;
for (StringTable::iterator i = table.begin(); i != table.end(); ++i) {
if (verbose && nthreads)
printf("%s %d\n", i->first.c_str(), i->second);
if (!silent && count_collisions) {
// it doesn't count real collisions in hash_map, a mask should be applied on hash value
hashes[std::hash<MyString>()(i->first) & 0xFFFF]++;
}
n += i->second;
}
if (!silent && count_collisions) {
for (auto i = hashes.begin(); i != hashes.end(); ++i)
c += i->second - 1;
printf("hashes = %d collisions = %d ", static_cast<int>(hashes.size()), c);
c = 0;
hashes.clear();
}
if (!silent)
printf(
"total = %d unique = %u time = %g\n", n, unsigned(table.size()), (t1 - t0).seconds());
}
/// Generator of random words
struct Sound {
const char* chars;
int rates[3]; // beginning, middle, ending
};
Sound Vowels[] = {
{ "e", { 445, 6220, 1762 } }, { "a", { 704, 5262, 514 } }, { "i", { 402, 5224, 162 } },
{ "o", { 248, 3726, 191 } }, { "u", { 155, 1669, 23 } }, { "y", { 4, 400, 989 } },
{ "io", { 5, 512, 18 } }, { "ia", { 1, 329, 111 } }, { "ea", { 21, 370, 16 } },
{ "ou", { 32, 298, 4 } }, { "ie", { 0, 177, 140 } }, { "ee", { 2, 183, 57 } },
{ "ai", { 17, 206, 7 } }, { "oo", { 1, 215, 7 } }, { "au", { 40, 111, 2 } },
{ "ua", { 0, 102, 4 } }, { "ui", { 0, 104, 1 } }, { "ei", { 6, 94, 3 } },
{ "ue", { 0, 67, 28 } }, { "ay", { 1, 42, 52 } }, { "ey", { 1, 14, 80 } },
{ "oa", { 5, 84, 3 } }, { "oi", { 2, 81, 1 } }, { "eo", { 1, 71, 5 } },
{ "iou", { 0, 61, 0 } }, { "oe", { 2, 46, 9 } }, { "eu", { 12, 43, 0 } },
{ "iu", { 0, 45, 0 } }, { "ya", { 12, 19, 5 } }, { "ae", { 7, 18, 10 } },
{ "oy", { 0, 10, 13 } }, { "ye", { 8, 7, 7 } }, { "ion", { 0, 0, 20 } },
{ "ing", { 0, 0, 20 } }, { "ium", { 0, 0, 10 } }, { "er", { 0, 0, 20 } }
};
Sound Consonants[] = {
{ "r", { 483, 1414, 1110 } }, { "n", { 312, 1548, 1114 } }, { "t", { 363, 1653, 251 } },
{ "l", { 424, 1341, 489 } }, { "c", { 734, 735, 260 } }, { "m", { 732, 785, 161 } },
{ "d", { 558, 612, 389 } }, { "s", { 574, 570, 405 } }, { "p", { 519, 361, 98 } },
{ "b", { 528, 356, 30 } }, { "v", { 197, 598, 16 } }, { "ss", { 3, 191, 567 } },
{ "g", { 285, 430, 42 } }, { "st", { 142, 323, 180 } }, { "h", { 470, 89, 30 } },
{ "nt", { 0, 350, 231 } }, { "ng", { 0, 117, 442 } }, { "f", { 319, 194, 19 } },
{ "ll", { 1, 414, 83 } }, { "w", { 249, 131, 64 } }, { "k", { 154, 179, 47 } },
{ "nd", { 0, 279, 92 } }, { "bl", { 62, 235, 0 } }, { "z", { 35, 223, 16 } },
{ "sh", { 112, 69, 79 } }, { "ch", { 139, 95, 25 } }, { "th", { 70, 143, 39 } },
{ "tt", { 0, 219, 19 } }, { "tr", { 131, 104, 0 } }, { "pr", { 186, 41, 0 } },
{ "nc", { 0, 223, 2 } }, { "j", { 184, 32, 1 } }, { "nn", { 0, 188, 20 } },
{ "rt", { 0, 148, 51 } }, { "ct", { 0, 160, 29 } }, { "rr", { 0, 182, 3 } },
{ "gr", { 98, 87, 0 } }, { "ck", { 0, 92, 86 } }, { "rd", { 0, 81, 88 } },
{ "x", { 8, 102, 48 } }, { "ph", { 47, 101, 10 } }, { "br", { 115, 43, 0 } },
{ "cr", { 92, 60, 0 } }, { "rm", { 0, 131, 18 } }, { "ns", { 0, 124, 18 } },
{ "sp", { 81, 55, 4 } }, { "sm", { 25, 29, 85 } }, { "sc", { 53, 83, 1 } },
{ "rn", { 0, 100, 30 } }, { "cl", { 78, 42, 0 } }, { "mm", { 0, 116, 0 } },
{ "pp", { 0, 114, 2 } }, { "mp", { 0, 99, 14 } }, { "rs", { 0, 96, 16 } },
{ "rl", { 0, 97, 7 } }, { "rg", { 0, 81, 15 } }, { "pl", { 56, 39, 0 } },
{ "sn", { 32, 62, 1 } }, { "str", { 38, 56, 0 } }, { "dr", { 47, 44, 0 } },
{ "fl", { 77, 13, 1 } }, { "fr", { 77, 11, 0 } }, { "ld", { 0, 47, 38 } },
{ "ff", { 0, 62, 20 } }, { "lt", { 0, 61, 19 } }, { "rb", { 0, 75, 4 } },
{ "mb", { 0, 72, 7 } }, { "rc", { 0, 76, 1 } }, { "gg", { 0, 74, 1 } },
{ "pt", { 1, 56, 10 } }, { "bb", { 0, 64, 1 } }, { "sl", { 48, 17, 0 } },
{ "dd", { 0, 59, 2 } }, { "gn", { 3, 50, 4 } }, { "rk", { 0, 30, 28 } },
{ "nk", { 0, 35, 20 } }, { "gl", { 40, 14, 0 } }, { "wh", { 45, 6, 0 } },
{ "ntr", { 0, 50, 0 } }, { "rv", { 0, 47, 1 } }, { "ght", { 0, 19, 29 } },
{ "sk", { 23, 17, 5 } }, { "nf", { 0, 46, 0 } }, { "cc", { 0, 45, 0 } },
{ "ln", { 0, 41, 0 } }, { "sw", { 36, 4, 0 } }, { "rp", { 0, 36, 4 } },
{ "dn", { 0, 38, 0 } }, { "ps", { 14, 19, 5 } }, { "nv", { 0, 38, 0 } },
{ "tch", { 0, 21, 16 } }, { "nch", { 0, 26, 11 } }, { "lv", { 0, 35, 0 } },
{ "wn", { 0, 14, 21 } }, { "rf", { 0, 32, 3 } }, { "lm", { 0, 30, 5 } },
{ "dg", { 0, 34, 0 } }, { "ft", { 0, 18, 15 } }, { "scr", { 23, 10, 0 } },
{ "rch", { 0, 24, 6 } }, { "rth", { 0, 23, 7 } }, { "rh", { 13, 15, 0 } },
{ "mpl", { 0, 29, 0 } }, { "cs", { 0, 1, 27 } }, { "gh", { 4, 10, 13 } },
{ "ls", { 0, 23, 3 } }, { "ndr", { 0, 25, 0 } }, { "tl", { 0, 23, 1 } },
{ "ngl", { 0, 25, 0 } }, { "lk", { 0, 15, 9 } }, { "rw", { 0, 23, 0 } },
{ "lb", { 0, 23, 1 } }, { "tw", { 15, 8, 0 } }, { "chr", { 18, 4, 0 } },
{ "dl", { 0, 23, 0 } }, { "ctr", { 0, 22, 0 } }, { "nst", { 0, 21, 0 } },
{ "lc", { 0, 22, 0 } }, { "sch", { 16, 4, 0 } }, { "ths", { 0, 1, 20 } },
{ "nl", { 0, 21, 0 } }, { "lf", { 0, 15, 6 } }, { "ssn", { 0, 20, 0 } },
{ "xt", { 0, 18, 1 } }, { "xp", { 0, 20, 0 } }, { "rst", { 0, 15, 5 } },
{ "nh", { 0, 19, 0 } }, { "wr", { 14, 5, 0 } }
};
const int VowelsNumber = sizeof(Vowels) / sizeof(Sound);
const int ConsonantsNumber = sizeof(Consonants) / sizeof(Sound);
int VowelsRatesSum[3] = { 0, 0, 0 }, ConsonantsRatesSum[3] = { 0, 0, 0 };
int CountRateSum(Sound sounds[], const int num, const int part) {
int sum = 0;
for (int i = 0; i < num; i++)
sum += sounds[i].rates[part];
return sum;
}
const char* GetLetters(int type, const int part) {
Sound* sounds;
int rate, i = 0;
if (type & 1)
sounds = Vowels, rate = rand() % VowelsRatesSum[part];
else
sounds = Consonants, rate = rand() % ConsonantsRatesSum[part];
do {
rate -= sounds[i++].rates[part];
} while (rate > 0);
return sounds[--i].chars;
}
static void CreateData() {
for (int i = 0; i < 3; i++) {
ConsonantsRatesSum[i] = CountRateSum(Consonants, ConsonantsNumber, i);
VowelsRatesSum[i] = CountRateSum(Vowels, VowelsNumber, i);
}
for (int i = 0; i < N; ++i) {
int type = rand();
Data[i] = GetLetters(type++, 0);
for (int j = 0; j < type % size_factor; ++j)
Data[i] += GetLetters(type++, 1);
Data[i] += GetLetters(type, 2);
}
MyString planet = Data[12];
planet[0] = toupper(planet[0]);
MyString helloworld = Data[0];
helloworld[0] = toupper(helloworld[0]);
helloworld += ", " + Data[1] + " " + Data[2] + " " + Data[3] + " " + Data[4] + " " + Data[5];
if (!silent)
printf("Message from planet '%s': %s!\nAnalyzing whole text...\n",
planet.c_str(),
helloworld.c_str());
}
int main(int argc, char* argv[]) {
StringTable table;
oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now();
srand(2);
//! Working threads count
// The 1st argument is the function to obtain 'auto' value; the 2nd is the default value
// The example interprets 0 threads as "run serially, then fully subscribed"
utility::thread_number_range threads(utility::get_default_num_threads, 0);
utility::parse_cli_arguments(
argc,
argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.positional_arg(threads, "n-of-threads", utility::thread_number_range_desc)
.positional_arg(N, "n-of-strings", "number of strings")
.arg(verbose, "verbose", "verbose mode")
.arg(silent, "silent", "no output except elapsed time")
.arg(count_collisions, "count_collisions", "print the count of collisions"));
if (silent)
verbose = false;
Data = new MyString[N];
CreateData();
if (threads.first) {
for (int p = threads.first; p <= threads.last; p = threads.step(p)) {
if (!silent)
printf("threads = %d ", p);
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p);
CountOccurrences(p);
}
}
else { // Number of threads wasn't set explicitly. Run serial and parallel version
{ // serial run
if (!silent)
printf("serial run ");
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, 1);
CountOccurrences(1);
}
{ // parallel run (number of threads is selected automatically)
if (!silent)
printf("parallel run ");
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
utility::get_default_num_threads());
CountOccurrences(0);
}
}
delete[] Data;
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - mainStartTime).seconds());
return 0;
}
@@ -0,0 +1,6 @@
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
This directory contains examples of the `concurrent_priority_queue` container.
| Code sample name | Description
|:--- |:---
| shortpath | Solves the single source shortest path problem using a `concurrent_priority_queue` container.
@@ -0,0 +1,33 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(shortpath CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
add_executable(shortpath shortpath.cpp)
target_link_libraries(shortpath TBB::tbb Threads::Threads)
target_compile_options(shortpath PRIVATE ${TBB_CXX_STD_FLAG})
set(EXECUTABLE "$<TARGET_FILE:shortpath>")
set(ARGS 4 N=1000 start=0 end=999 verbose)
set(PERF_ARGS auto N=1000 start=0 end=99 silent)
add_execution_target(run_shortpath shortpath ${EXECUTABLE} "${ARGS}")
add_execution_target(perf_run_shortpath shortpath ${EXECUTABLE} "${PERF_ARGS}")
@@ -0,0 +1,36 @@
# Shortpath sample
This directory contains an example that solves the single source shortest path problem.
It is parameterized by `N`, a number of nodes, and a start and end node in `[0..N)`. A graph is generated with `N` nodes and some random number of connections between those nodes. A parallel algorithm based on `A*` is used to find the shortest path.
This algorithm varies from serial `A*` in that it needs to add nodes back to the open set when the `g` estimate (shortest path from start to the node) is improved, even if the node has already been "visited". This is because nodes are added and removed from the open-set in parallel, resulting in some less optimal paths being explored. The open-set is implemented with the `concurrent_priority_queue`.
Note that since we re-visit nodes, the `f` estimate (on which the priority queue is sorted) is not technically needed, so we could use this same parallel algorithm with just a `concurrent_queue`. However, keeping the `f` estimate and using `concurrent_priority_queue` results in much better performance.
Silent mode prints run time only, regular mode prints the shortest path length, and verbose mode prints out the shortest path.
The generated graph follows a pattern in which the closer two pairs of node ids are together, the fewer hops there are in a typical path between those nodes. So, for example, the path between 5 and 7 likely has few hops whereas 14 to 78 has more and 0 to 9999 has even more, etc.
## Building the example
```
cmake <path_to_example>
cmake --build .
```
## Running the sample
### Predefined make targets
* `make run_shortpath` - executes the example with predefined parameters.
* `make perf_run_shortpath` - executes the example with suggested parameters to measure the oneTBB performance.
### Application parameters
Usage:
```
shortpath [#threads=value] [verbose] [silent] [N=value] [start=value] [end=value] [-h] [#threads]
```
* `-h` - prints the help for command line options.
* `n-of-threads` - number of threads to use; a range of the form low[:high], where low and optional high are non-negative integers or `auto` for a platform-specific default number.
* `verbose` - prints diagnostic output to screen.
* `silent` - no output except elapsed time.
* `N` - number of nodes in graph.
* `start` - node to start path at.
* `end` - node to end path at.
@@ -0,0 +1,340 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cmath>
#include <cstdio>
#include <vector>
#include <atomic>
#include "oneapi/tbb/tick_count.h"
#include "oneapi/tbb/task_group.h"
#include "oneapi/tbb/concurrent_priority_queue.h"
#include "oneapi/tbb/spin_mutex.h"
#include "oneapi/tbb/parallel_for.h"
#include "oneapi/tbb/blocked_range.h"
#include "oneapi/tbb/global_control.h"
#include "common/utility/utility.hpp"
#include "common/utility/fast_random.hpp"
#include "common/utility/get_default_num_threads.hpp"
#if defined(_MSC_VER) && defined(_Wp64)
// Workaround for overzealous compiler warnings in /Wp64 mode
#pragma warning(disable : 4267)
#endif /* _MSC_VER && _Wp64 */
struct point {
double x, y;
point() {}
point(double _x, double _y) : x(_x), y(_y) {}
point(const point& p) : x(p.x), y(p.y) {}
};
double get_distance(const point& p1, const point& p2) {
double xdiff = p1.x - p2.x, ydiff = p1.y - p2.y;
return sqrt(xdiff * xdiff + ydiff * ydiff);
}
// generates random points on 2D plane within a box of maxsize width & height
point generate_random_point(utility::FastRandom& mr) {
const std::size_t maxsize = 500;
double x = (double)(mr.get() % maxsize);
double y = (double)(mr.get() % maxsize);
return point(x, y);
}
// weighted toss makes closer nodes (in the point vector) heavily connected
bool die_toss(std::size_t a, std::size_t b, utility::FastRandom& mr) {
int node_diff = std::abs(int(a - b));
// near nodes
if (node_diff < 16)
return true;
// mid nodes
if (node_diff < 64)
return ((int)mr.get() % 8 == 0);
// far nodes
if (node_diff < 512)
return ((int)mr.get() % 16 == 0);
return false;
}
typedef std::vector<point> point_set;
typedef std::size_t vertex_id;
typedef std::pair<vertex_id, double> vertex_rec;
typedef std::vector<std::vector<vertex_id>> edge_set;
bool verbose = false; // prints bin details and other diagnostics to screen
bool silent = false; // suppress all output except for time
std::size_t N = 1000; // number of vertices
std::size_t src = 0; // start of path
std::size_t dst = N - 1; // end of path
double INF = 100000.0; // infinity
std::size_t grainsize = 16; // number of vertices per task on average
std::size_t max_spawn; // max tasks to spawn
std::atomic<std::size_t> num_spawn; // number of active tasks
point_set vertices; // vertices
edge_set edges; // edges
std::vector<vertex_id> predecessor; // for recreating path from src to dst
std::vector<double> f_distance; // estimated distances at particular vertex
std::vector<double> g_distance; // current shortest distances from src vertex
oneapi::tbb::spin_mutex* locks; // a lock for each vertex
oneapi::tbb::task_group* sp_group; // task group for tasks executing sub-problems
struct compare_f {
bool operator()(const vertex_rec& u, const vertex_rec& v) const {
return u.second > v.second;
}
};
oneapi::tbb::concurrent_priority_queue<vertex_rec, compare_f> open_set; // tentative vertices
void shortpath_helper();
void shortpath() {
sp_group = new oneapi::tbb::task_group;
g_distance[src] = 0.0; // src's distance from src is zero
f_distance[src] =
get_distance(vertices[src], vertices[dst]); // estimate distance from src to dst
open_set.emplace(src, f_distance[src]); // emplace src into open_set
sp_group->run([]() {
shortpath_helper();
});
sp_group->wait();
delete sp_group;
}
void shortpath_helper() {
vertex_rec u_rec;
while (open_set.try_pop(u_rec)) {
vertex_id u = u_rec.first;
if (u == dst)
continue;
double f = u_rec.second;
double old_g_u = 0.0;
{
oneapi::tbb::spin_mutex::scoped_lock l(locks[u]);
if (f > f_distance[u])
continue; // prune search space
old_g_u = g_distance[u];
}
for (std::size_t i = 0; i < edges[u].size(); ++i) {
vertex_id v = edges[u][i];
double new_g_v = old_g_u + get_distance(vertices[u], vertices[v]);
double new_f_v = 0.0;
// the push flag lets us move some work out of the critical section below
bool push = false;
{
oneapi::tbb::spin_mutex::scoped_lock l(locks[v]);
if (new_g_v < g_distance[v]) {
predecessor[v] = u;
g_distance[v] = new_g_v;
new_f_v = f_distance[v] =
g_distance[v] + get_distance(vertices[v], vertices[dst]);
push = true;
}
}
if (push) {
open_set.push(std::make_pair(v, new_f_v));
std::size_t n_spawn = ++num_spawn;
if (n_spawn < max_spawn) {
sp_group->run([] {
shortpath_helper();
});
}
else
--num_spawn;
}
}
}
--num_spawn;
}
void make_path(vertex_id src, vertex_id dst, std::vector<vertex_id>& path) {
vertex_id at = predecessor[dst];
if (at == N)
path.push_back(src);
else if (at == src) {
path.push_back(src);
path.push_back(dst);
}
else {
make_path(src, at, path);
path.push_back(dst);
}
}
void print_path() {
std::vector<vertex_id> path;
double path_length = 0.0;
make_path(src, dst, path);
if (verbose)
printf("\n ");
for (std::size_t i = 0; i < path.size(); ++i) {
if (path[i] != dst) {
double seg_length = get_distance(vertices[path[i]], vertices[path[i + 1]]);
if (verbose)
printf("%6.1f ", seg_length);
path_length += seg_length;
}
else if (verbose)
printf("\n");
}
if (verbose) {
for (std::size_t i = 0; i < path.size(); ++i) {
if (path[i] != dst)
printf("(%4d)------>", (int)path[i]);
else
printf("(%4d)\n", (int)path[i]);
}
}
if (verbose)
printf("Total distance = %5.1f\n", path_length);
else if (!silent)
printf(" %5.1f\n", path_length);
}
void InitializeGraph() {
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
utility::get_default_num_threads());
vertices.resize(N);
edges.resize(N);
predecessor.resize(N);
g_distance.resize(N);
f_distance.resize(N);
locks = new oneapi::tbb::spin_mutex[N];
if (verbose)
printf("Generating vertices...\n");
oneapi::tbb::parallel_for(
oneapi::tbb::blocked_range<std::size_t>(0, N, 64),
[&](oneapi::tbb::blocked_range<std::size_t>& r) {
utility::FastRandom my_random(r.begin());
for (std::size_t i = r.begin(); i != r.end(); ++i) {
vertices[i] = generate_random_point(my_random);
}
},
oneapi::tbb::simple_partitioner());
if (verbose)
printf("Generating edges...\n");
oneapi::tbb::parallel_for(
oneapi::tbb::blocked_range<std::size_t>(0, N, 64),
[&](oneapi::tbb::blocked_range<std::size_t>& r) {
utility::FastRandom my_random(r.begin());
for (std::size_t i = r.begin(); i != r.end(); ++i) {
for (std::size_t j = 0; j < i; ++j) {
if (die_toss(i, j, my_random))
edges[i].push_back(j);
}
}
},
oneapi::tbb::simple_partitioner());
for (std::size_t i = 0; i < N; ++i) {
for (std::size_t j = 0; j < edges[i].size(); ++j) {
vertex_id k = edges[i][j];
edges[k].push_back(i);
}
}
if (verbose)
printf("Done.\n");
}
void ReleaseGraph() {
delete[] locks;
}
void ResetGraph() {
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
utility::get_default_num_threads());
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, N),
[&](oneapi::tbb::blocked_range<std::size_t>& r) {
for (std::size_t i = r.begin(); i != r.end(); ++i) {
f_distance[i] = g_distance[i] = INF;
predecessor[i] = N;
}
});
}
int main(int argc, char* argv[]) {
utility::thread_number_range threads(utility::get_default_num_threads);
utility::parse_cli_arguments(
argc,
argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.positional_arg(threads, "#threads", utility::thread_number_range_desc)
.arg(verbose, "verbose", " print diagnostic output to screen")
.arg(silent, "silent", " limits output to timing info; overrides verbose")
.arg(N, "N", " number of vertices")
.arg(src, "start", " start of path")
.arg(dst, "end", " end of path"));
if (silent)
verbose = false; // make silent override verbose
else
printf("shortpath will run with %d vertices to find shortest path between vertices"
" %d and %d using %d:%d threads.\n",
(int)N,
(int)src,
(int)dst,
(int)threads.first,
(int)threads.last);
if (dst >= N) {
if (verbose)
printf("end value %d is invalid for %d vertices; correcting to %d\n",
(int)dst,
(int)N,
(int)N - 1);
dst = N - 1;
}
num_spawn = 0;
max_spawn = N / grainsize;
oneapi::tbb::tick_count t0, t1;
InitializeGraph();
for (int n_thr = threads.first; n_thr <= threads.last; n_thr = threads.step(n_thr)) {
ResetGraph();
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, n_thr);
t0 = oneapi::tbb::tick_count::now();
shortpath();
t1 = oneapi::tbb::tick_count::now();
if (!silent) {
if (predecessor[dst] != N) {
printf("%d threads: [%6.6f] The shortest path from vertex %d to vertex %d is:",
(int)n_thr,
(t1 - t0).seconds(),
(int)src,
(int)dst);
print_path();
}
else {
printf("%d threads: [%6.6f] There is no path from vertex %d to vertex %d\n",
(int)n_thr,
(t1 - t0).seconds(),
(int)src,
(int)dst);
}
}
else
utility::report_elapsed_time((t1 - t0).seconds());
}
ReleaseGraph();
return 0;
}
+6
View File
@@ -0,0 +1,6 @@
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
This directory contains the examples referenced by the [oneAPI Threading Building Blocks Get Started Guide](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html)
| Code sample name | Description
|:--- |:---
| sub_string_finder | Finds largest matching substrings.
@@ -0,0 +1,46 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(sub_string_finder_simple CXX)
project(sub_string_finder_extended CXX)
project(sub_string_finder_pretty CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
add_executable(sub_string_finder_simple sub_string_finder.cpp)
add_executable(sub_string_finder_extended sub_string_finder_extended.cpp)
add_executable(sub_string_finder_pretty sub_string_finder_pretty.cpp)
target_link_libraries(sub_string_finder_simple TBB::tbb Threads::Threads)
target_link_libraries(sub_string_finder_extended TBB::tbb Threads::Threads)
target_link_libraries(sub_string_finder_pretty TBB::tbb Threads::Threads)
target_compile_options(sub_string_finder_simple PRIVATE ${TBB_CXX_STD_FLAG})
target_compile_options(sub_string_finder_extended PRIVATE ${TBB_CXX_STD_FLAG})
target_compile_options(sub_string_finder_pretty PRIVATE ${TBB_CXX_STD_FLAG})
add_custom_target(sub_string_finder)
add_dependencies(sub_string_finder sub_string_finder_simple sub_string_finder_extended sub_string_finder_pretty)
set(EXECUTABLE "$<TARGET_FILE:sub_string_finder_extended>")
set(LIGHT_EXECUTABLE "$<TARGET_FILE:sub_string_finder_simple>")
set(ARGS "")
set(LIGHT_ARGS "silent")
add_execution_target(run_sub_string_finder sub_string_finder ${EXECUTABLE} "${ARGS}")
add_execution_target(light_test_sub_string_finder sub_string_finder ${LIGHT_EXECUTABLE} "${LIGHT_ARGS}")
@@ -0,0 +1,31 @@
# Sub_string_finder sample
An example that uses the `parallel_for` template in a substring matching program. The [oneAPI Threading Building Blocks [](https://software.intel.com/content/www/us/en/develop/documentation/get-started-with-onetbb/top.html) describes this example.
For each position in a string, the program displays the length of the largest matching substring elsewhere in the string. The program also displays the location of a largest match for each position. Consider the string "babba" as an example. Starting at position 0, "ba" is the largest substring with a match elsewhere in the string (position 3).
## Building the example
```
cmake <path_to_example>
cmake --build .
```
### Predefined make targets
* `make sub_string_finder_simple` - builds the example as it appears in the Get Started Guide.
* `make sub_string_finder_extended` - builds the similar example with more attractive printing of the results.
* `make sub_string_finder_pretty` - builds the example extended with a sequential implementation.
* `make sub_string_finder` - builds all sample versions.
## Running the sample
### Predefined make targets
* `make run_sub_string_finder` - executes the example with predefined parameters.
* `make light_test_sub_string_finder` - executes the example with suggested parameters to reduce execution time.
### Application parameters
Usage:
```
sub_string_finder_simple
sub_string_finder_extended
sub_string_finder_pretty
```
The example does not requires application parameters.
@@ -0,0 +1,90 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> // std::max
#include "oneapi/tbb/parallel_for.h"
#include "oneapi/tbb/blocked_range.h"
#include "common/utility/utility.hpp"
bool silent = false;
static const std::size_t N = 23;
class SubStringFinder {
const std::string &str;
std::vector<std::size_t> &max_array;
std::vector<std::size_t> &pos_array;
public:
void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
for (std::size_t i = r.begin(); i != r.end(); ++i) {
std::size_t max_size = 0, max_pos = 0;
for (std::size_t j = 0; j < str.size(); ++j) {
if (j != i) {
std::size_t limit = str.size() - (std::max)(i, j);
for (std::size_t k = 0; k < limit; ++k) {
if (str[i + k] != str[j + k])
break;
if (k > max_size) {
max_size = k;
max_pos = j;
}
}
}
}
max_array[i] = max_size;
pos_array[i] = max_pos;
}
}
SubStringFinder(const std::string &s, std::vector<std::size_t> &m, std::vector<std::size_t> &p)
: str(s),
max_array(m),
pos_array(p) {}
};
int main(int argc, char *argv[]) {
// command line parsing
utility::parse_cli_arguments(argc,
argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.arg(silent, "silent", "no output"));
std::string str[N] = { std::string("a"), std::string("b") };
for (std::size_t i = 2; i < N; ++i)
str[i] = str[i - 1] + str[i - 2];
std::string &to_scan = str[N - 1];
const std::size_t num_elem = to_scan.size();
std::vector<std::size_t> max(num_elem);
std::vector<std::size_t> pos(num_elem);
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem),
SubStringFinder(to_scan, max, pos));
for (std::size_t i = 0; i < num_elem; ++i)
if (!silent)
std::cout << " " << max[i] << "(" << pos[i] << ")"
<< "\n";
return 0;
}
@@ -0,0 +1,131 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> // std::max
#include "oneapi/tbb/parallel_for.h"
#include "oneapi/tbb/blocked_range.h"
#include "oneapi/tbb/tick_count.h"
static const std::size_t N = 22;
void SerialSubStringFinder(const std::string &str,
std::vector<std::size_t> &max_array,
std::vector<std::size_t> &pos_array) {
for (std::size_t i = 0; i < str.size(); ++i) {
std::size_t max_size = 0, max_pos = 0;
for (std::size_t j = 0; j < str.size(); ++j)
if (j != i) {
std::size_t limit = str.size() - (std::max)(i, j);
for (std::size_t k = 0; k < limit; ++k) {
if (str[i + k] != str[j + k])
break;
if (k > max_size) {
max_size = k;
max_pos = j;
}
}
}
max_array[i] = max_size;
pos_array[i] = max_pos;
}
}
class SubStringFinder {
const char *str;
const std::size_t len;
std::size_t *max_array;
std::size_t *pos_array;
public:
void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
for (std::size_t i = r.begin(); i != r.end(); ++i) {
std::size_t max_size = 0, max_pos = 0;
for (std::size_t j = 0; j < len; ++j) {
if (j != i) {
std::size_t limit = len - (std::max)(i, j);
for (std::size_t k = 0; k < limit; ++k) {
if (str[i + k] != str[j + k])
break;
if (k > max_size) {
max_size = k;
max_pos = j;
}
}
}
}
max_array[i] = max_size;
pos_array[i] = max_pos;
}
}
// We do not use std::vector for compatibility with offload execution
SubStringFinder(const char *s, const std::size_t s_len, std::size_t *m, std::size_t *p)
: str(s),
len(s_len),
max_array(m),
pos_array(p) {}
};
int main() {
std::string str[N] = { std::string("a"), std::string("b") };
for (std::size_t i = 2; i < N; ++i)
str[i] = str[i - 1] + str[i - 2];
std::string &to_scan = str[N - 1];
const std::size_t num_elem = to_scan.size();
std::vector<std::size_t> max1(num_elem);
std::vector<std::size_t> pos1(num_elem);
std::vector<std::size_t> max2(num_elem);
std::vector<std::size_t> pos2(num_elem);
std::cout << " Done building string."
<< "\n";
oneapi::tbb::tick_count serial_t0 = oneapi::tbb::tick_count::now();
SerialSubStringFinder(to_scan, max2, pos2);
oneapi::tbb::tick_count serial_t1 = oneapi::tbb::tick_count::now();
std::cout << " Done with serial version."
<< "\n";
oneapi::tbb::tick_count parallel_t0 = oneapi::tbb::tick_count::now();
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem, 100),
SubStringFinder(to_scan.c_str(), num_elem, &max1[0], &pos1[0]));
oneapi::tbb::tick_count parallel_t1 = oneapi::tbb::tick_count::now();
std::cout << " Done with parallel version."
<< "\n";
for (std::size_t i = 0; i < num_elem; ++i) {
if (max1[i] != max2[i] || pos1[i] != pos2[i]) {
std::cout << "ERROR: Serial and Parallel Results are Different!"
<< "\n";
break;
}
}
std::cout << " Done validating results."
<< "\n";
std::cout << "Serial version ran in " << (serial_t1 - serial_t0).seconds() << " seconds"
<< "\n"
<< "Parallel version ran in " << (parallel_t1 - parallel_t0).seconds() << " seconds"
<< "\n"
<< "Resulting in a speedup of "
<< (serial_t1 - serial_t0).seconds() / (parallel_t1 - parallel_t0).seconds() << "\n";
return 0;
}
@@ -0,0 +1,94 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <algorithm> // std::max
#include "oneapi/tbb/parallel_for.h"
#include "oneapi/tbb/blocked_range.h"
static const std::size_t N = 9;
class SubStringFinder {
const std::string &str;
std::vector<std::size_t> &max_array;
std::vector<std::size_t> &pos_array;
public:
void operator()(const oneapi::tbb::blocked_range<std::size_t> &r) const {
for (std::size_t i = r.begin(); i != r.end(); ++i) {
std::size_t max_size = 0, max_pos = 0;
for (std::size_t j = 0; j < str.size(); ++j) {
if (j != i) {
std::size_t limit = str.size() - (std::max)(i, j);
for (std::size_t k = 0; k < limit; ++k) {
if (str[i + k] != str[j + k])
break;
if (k + 1 > max_size) {
max_size = k + 1;
max_pos = j;
}
}
}
}
max_array[i] = max_size;
pos_array[i] = max_pos;
}
}
SubStringFinder(const std::string &s, std::vector<std::size_t> &m, std::vector<std::size_t> &p)
: str(s),
max_array(m),
pos_array(p) {}
};
int main() {
std::string str[N] = { std::string("a"), std::string("b") };
for (std::size_t i = 2; i < N; ++i)
str[i] = str[i - 1] + str[i - 2];
std::string &to_scan = str[N - 1];
const std::size_t num_elem = to_scan.size();
std::cout << "String to scan: " << to_scan << "\n";
std::vector<std::size_t> max(num_elem);
std::vector<std::size_t> pos(num_elem);
oneapi::tbb::parallel_for(oneapi::tbb::blocked_range<std::size_t>(0, num_elem, 100),
SubStringFinder(to_scan, max, pos));
for (std::size_t i = 0; i < num_elem; ++i) {
for (std::size_t j = 0; j < num_elem; ++j) {
if (j >= i && j < i + max[i])
std::cout << "_";
else
std::cout << " ";
}
std::cout << "\n" << to_scan << "\n";
for (std::size_t j = 0; j < num_elem; ++j) {
if (j >= pos[i] && j < pos[i] + max[i])
std::cout << "*";
else
std::cout << " ";
}
std::cout << "\n";
}
return 0;
}
+11
View File
@@ -0,0 +1,11 @@
# Code Samples of oneAPI Threading Building Blocks (oneTBB)
Examples using oneTBB Flow Graph feature.
| Code sample name | Description
|:--- |:---
| binpack | A solution to the binpacking problem using a `queue_node`, a `buffer_node` and `function_node`s.
| cholesky | Several versions of Cholesky Factorization algorithm implementation.
| dining_philosophers | An implementation of dining philosophers in graph using the reserving `join_node`.
| fgbzip2 | A parallel implementation of bzip2 block-sorting file compressor.
| logic_sim | An example of a collection of digital logic gates that can be easily composed into larger circuits.
| som | An example of a Kohonen Self-Organizing Map using cancellation.
+33
View File
@@ -0,0 +1,33 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(binpack CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
add_executable(binpack binpack.cpp)
target_link_libraries(binpack TBB::tbb Threads::Threads)
target_compile_options(binpack PRIVATE ${TBB_CXX_STD_FLAG})
set(EXECUTABLE "$<TARGET_FILE:binpack>")
set(ARGS 4 elements_num=1000)
set(PERF_ARGS auto elements_num=1000 silent)
add_execution_target(run_binpack binpack ${EXECUTABLE} "${ARGS}")
add_execution_target(perf_run_binpack binpack ${EXECUTABLE} "${PERF_ARGS}")
+29
View File
@@ -0,0 +1,29 @@
# Binpack sample
This directory contains an `oneapi::tbb::flow` example that performs binpacking of `N` integer values into a near-optimal number of bins of capacity `V`.
It features a `source_node` which passes randomly generated integer values of `size <= V` to a `queue_node`. Multiple function nodes set about taking values from this `queue_node` and packing them into bins according to a best-fit policy. Items that cannot be made to fit are rejected and returned to the queue. When a bin is packed as well as it can be, it is passed to a `buffer_node` where it waits to be picked up by another `function_node`. This final function node gathers stats about the bin and optionally prints its contents. When all bins are accounted for, it optionally prints a summary of the quality of the bin-packing.
## Building the example
```
cmake <path_to_example>
cmake --build .
```
## Running the sample
### Predefined make targets
* `make run_binpack` - executes the example with predefined parameters.
* `make perf_run_binpack` - executes the example with suggested parameters to measure the oneTBB performance.
### Application parameters
Usage:
```
binpack [#threads=value] [verbose] [silent] [elements_num=value] [bin_capacity=value] [#packers=value] [optimality=value] [-h] [#threads]
```
* `-h` - prints the help for command line options.
* `#threads` - the number of threads to use; a range of the form low\[:high\] where low and optional high are non-negative integers, or `auto` for a platform-specific default number.
* `verbose` - prints diagnostic output to screen.
* `silent` - limits output to timing info; overrides verbose.
* `N` - number of values to pack.
* `V` - capacity of each bin.
* `#packers` - number of concurrent bin packers to use (`default=#threads`).
* `optimality` - controls optimality of solution; 1 is highest, use larger numbers for less optimal but faster solution.
+337
View File
@@ -0,0 +1,337 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* Bin-packing algorithm that attempts to use minimal number of bins B of
size desired_bin_capacity to contain elements_num items of varying sizes. */
#include <cmath>
#include <string>
#include <iostream>
#include <tuple>
#include <vector>
#include <atomic>
#include <algorithm>
#include "oneapi/tbb/tick_count.h"
#include "oneapi/tbb/flow_graph.h"
#include "oneapi/tbb/global_control.h"
#include "common/utility/utility.hpp"
#include "common/utility/get_default_num_threads.hpp"
typedef std::size_t size_type; // to represent non-zero indices, capacities, etc.
typedef std::size_t value_type; // the type of items we are attempting to pack into bins
typedef std::vector<value_type> bin; // we use a simple vector to represent a bin
// Our bin packers will be function nodes in the graph that take value_type items and
// return a dummy value. They will also implicitly send packed bins to the bin_buffer
// node, and unused items back to the value_pool node:
typedef oneapi::tbb::flow::
multifunction_node<value_type, std::tuple<value_type, bin>, oneapi::tbb::flow::rejecting>
bin_packer;
// Items are placed into a pool that all bin packers grab from, represent by a queue_node:
typedef oneapi::tbb::flow::queue_node<value_type> value_pool;
// Packed bins are placed in this buffer waiting to be serially printed and/or accounted for:
typedef oneapi::tbb::flow::buffer_node<bin> bin_buffer;
// Packed bins are taken from the_bin_buffer and processed by the_writer:
typedef oneapi::tbb::flow::
function_node<bin, oneapi::tbb::flow::continue_msg, oneapi::tbb::flow::rejecting>
bin_writer;
// Items are injected into the graph when this node sends them to the_value_pool:
typedef oneapi::tbb::flow::input_node<value_type> value_source;
// User-specified globals with default values
size_type desired_bin_capacity = 42;
size_type elements_num = 1000; // number of elements to generate
bool verbose = false; // prints bin details and other diagnostics to screen
bool silent = false; // suppress all output except for time
int num_bin_packers = -1; // number of concurrent bin packers in operation; default is #threads;
// larger values can result in more bins at less than full capacity
size_type optimality =
1; // 1 (default) is highest the algorithm can obtain; larger numbers run faster
// Calculated globals
size_type bins_num_min; // lower bound on the optimal number of bins
size_type bins_num; // the answer, i.e. number of bins used by the algorithm
std::vector<size_type> input_array; // stores randomly generated input values
value_type item_sum; // sum of all randomly generated input values
std::atomic<value_type> packed_sum; // sum of all values currently packed into all bins
std::atomic<size_type> packed_items; // number of values currently packed into all bins
std::atomic<size_type> active_bins; // number of active bin_packers
std::vector<bin_packer*> bins; // the array of bin packers
// This class is the Body type for bin_packer
class bin_filler {
typedef bin_packer::output_ports_type ports_type;
bin my_bin; // the current bin that this bin_filler is packing
size_type
my_used; // capacity of bin used by current contents (not to be confused with my_bin.size())
size_type relax,
relax_val; // relaxation counter for determining when to settle for a non-full bin
bin_packer* my_bin_packer; // ptr to the bin packer that this body object is associated with
size_type bin_index; // index of the encapsulating bin packer in the global bins array
value_type looking_for; // the minimum size of item this bin_packer will accept
value_pool* the_value_pool; // the queue of incoming values
bool done; // flag to indicate that this binpacker has been deactivated
public:
bin_filler(std::size_t bidx, value_pool* _q)
: my_used(0),
relax(0),
relax_val(0),
my_bin_packer(nullptr),
bin_index(bidx),
looking_for(desired_bin_capacity),
the_value_pool(_q),
done(false) {}
void operator()(const value_type& item, ports_type& p) {
if (!my_bin_packer)
my_bin_packer = bins[bin_index];
if (done)
// this bin_packer is done packing items; put item back to pool
std::get<0>(p).try_put(item);
else if (
item >
desired_bin_capacity) { // signal that packed_sum has reached item_sum at some point
size_type remaining = active_bins--;
if (remaining == 1 &&
packed_sum == item_sum) { // this is the last bin and it has seen everything
// this bin_packer may not have seen everything, so stay active
if (my_used > 0)
std::get<1>(p).try_put(my_bin);
my_bin.clear();
my_used = 0;
looking_for = desired_bin_capacity;
++active_bins;
}
else if (remaining == 1) { // this is the last bin, but there are remaining items
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
++active_bins;
}
else if (remaining > 1) { // this is not the last bin; deactivate
// this bin is ill-utilized; throw back items and deactivate
if (my_used < desired_bin_capacity / (1 + optimality * .1)) {
packed_sum -= my_used;
packed_items -= my_bin.size();
for (size_type i = 0; i < my_bin.size(); ++i)
std::get<0>(p).try_put(my_bin[i]);
oneapi::tbb::flow::remove_edge(*the_value_pool, *my_bin_packer); // deactivate
done = true;
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
}
else { // this bin is well-utilized; send out bin and deactivate
oneapi::tbb::flow::remove_edge(*the_value_pool,
*my_bin_packer); // build no more bins
done = true;
if (my_used > 0)
std::get<1>(p).try_put(my_bin);
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
}
}
}
else if (item <= desired_bin_capacity - my_used &&
item >= looking_for) { // this item can be packed
my_bin.push_back(item);
my_used += item;
packed_sum += item;
++packed_items;
looking_for = desired_bin_capacity - my_used;
relax = 0;
if (packed_sum == item_sum) {
std::get<0>(p).try_put(desired_bin_capacity + 1); // send out signal
}
if (my_used == desired_bin_capacity) {
std::get<1>(p).try_put(my_bin);
my_bin.clear();
my_used = 0;
looking_for = desired_bin_capacity;
}
}
else { // this item can't be packed; relax constraints
++relax;
// this bin_packer has looked through enough items
if (relax >= (elements_num - packed_items) / optimality) {
relax = 0;
--looking_for; // accept a wider range of items
if (looking_for == 0 && my_used < desired_bin_capacity / (1 + optimality * .1) &&
my_used > 0 && active_bins > 1) {
// this bin_packer is ill-utilized and can't find items; deactivate and throw back items
size_type remaining = active_bins--;
if (remaining > 1) { // not the last bin_packer
oneapi::tbb::flow::remove_edge(*the_value_pool,
*my_bin_packer); // deactivate
done = true;
}
else
active_bins++; // can't deactivate last bin_packer
packed_sum -= my_used;
packed_items -= my_bin.size();
for (size_type i = 0; i < my_bin.size(); ++i)
std::get<0>(p).try_put(my_bin[i]);
my_bin.clear();
my_used = 0;
}
else if (looking_for == 0 &&
(my_used >= desired_bin_capacity / (1 + optimality * .1) ||
active_bins == 1)) {
// this bin_packer can't find items but is well-utilized, so send it out and reset
std::get<1>(p).try_put(my_bin);
my_bin.clear();
my_used = 0;
looking_for = desired_bin_capacity;
}
}
std::get<0>(p).try_put(item); // put unused item back to pool
}
}
};
// input node uses this to send the values to the value_pool
class item_generator {
size_type counter;
public:
item_generator() : counter(0) {}
value_type operator()(oneapi::tbb::flow_control& fc) {
if (counter < elements_num) {
value_type result = input_array[counter];
++counter;
return result;
}
fc.stop();
return value_type{};
}
};
// the terminal function_node uses this to gather stats and print bin information
class bin_printer {
value_type running_count;
size_type item_count;
value_type my_min, my_max;
double avg;
public:
bin_printer()
: running_count(0),
item_count(0),
my_min(desired_bin_capacity),
my_max(0),
avg(0) {}
oneapi::tbb::flow::continue_msg operator()(bin b) {
value_type sum = 0;
++bins_num;
if (verbose)
std::cout << "[ ";
for (size_type i = 0; i < b.size(); ++i) {
if (verbose)
std::cout << b[i] << " ";
sum += b[i];
++item_count;
}
my_min = std::min(sum, my_min);
my_max = std::max(sum, my_max);
avg += sum;
running_count += sum;
if (verbose) {
std::cout << "]=" << sum << "; Done/Packed/Total cap: " << running_count << "/"
<< packed_sum << "/" << item_sum << " items:" << item_count << "/"
<< packed_items << "/" << elements_num << " bins_num=" << bins_num << "\n";
}
if (item_count == elements_num) { // should be the last; print stats
avg = avg / (double)bins_num;
if (!silent)
std::cout << "SUMMARY: #Bins used: " << bins_num << "; Avg size: " << avg
<< "; Max size: " << my_max << "; Min size: " << my_min << "\n"
<< " Lower bound on optimal #bins: " << bins_num_min
<< "; Start #bins: " << num_bin_packers << "\n";
}
return oneapi::tbb::flow::continue_msg(); // need to return something
}
};
int main(int argc, char* argv[]) {
utility::thread_number_range threads(utility::get_default_num_threads);
utility::parse_cli_arguments(
argc,
argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.positional_arg(threads, "#threads", utility::thread_number_range_desc)
.arg(verbose, "verbose", " print diagnostic output to screen")
.arg(silent, "silent", " limits output to timing info; overrides verbose")
.arg(elements_num, "elements_num", " number of values to pack")
.arg(desired_bin_capacity, "bin_capacity", " capacity of each bin")
.arg(num_bin_packers,
"#packers",
" number of concurrent bin packers to use "
"(default=#threads)")
.arg(optimality,
"optimality",
"controls optimality of solution; 1 is highest, use\n"
" larger numbers for less optimal but faster solution"));
if (silent)
verbose = false; // make silent override verbose
// Generate random input data
srand(42);
input_array.resize(elements_num);
item_sum = 0;
for (auto& item : input_array) {
item = rand() % desired_bin_capacity + 1; // generate items that fit in a bin
item_sum += item;
}
bins_num_min = (item_sum % desired_bin_capacity) ? item_sum / desired_bin_capacity + 1
: item_sum / desired_bin_capacity;
oneapi::tbb::tick_count start = oneapi::tbb::tick_count::now();
for (int p = threads.first; p <= threads.last; p = threads.step(p)) {
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism, p);
packed_sum = 0;
packed_items = 0;
bins_num = 0;
if (num_bin_packers == -1)
num_bin_packers = p;
active_bins = num_bin_packers;
if (!silent)
std::cout << "binpack running with " << item_sum << " capacity over " << elements_num
<< " items, optimality=" << optimality << ", " << num_bin_packers
<< " bins of capacity=" << desired_bin_capacity << " on " << p << " threads."
<< "\n";
oneapi::tbb::flow::graph g;
value_source the_source(g, item_generator());
value_pool the_value_pool(g);
oneapi::tbb::flow::make_edge(the_source, the_value_pool);
bin_buffer the_bin_buffer(g);
bins.resize(num_bin_packers);
for (int i = 0; i < num_bin_packers; ++i) {
bins[i] = new bin_packer(g, 1, bin_filler(i, &the_value_pool));
oneapi::tbb::flow::make_edge(the_value_pool, *(bins[i]));
oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<0>(*(bins[i])),
the_value_pool);
oneapi::tbb::flow::make_edge(oneapi::tbb::flow::output_port<1>(*(bins[i])),
the_bin_buffer);
}
bin_writer the_writer(g, 1, bin_printer());
make_edge(the_bin_buffer, the_writer);
the_source.activate();
g.wait_for_all();
for (int i = 0; i < num_bin_packers; ++i) {
delete bins[i];
}
}
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - start).seconds());
return 0;
}
+43
View File
@@ -0,0 +1,43 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(cholesky CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
# TODO: Consider using FindMKL module
find_library(MKL_INTEL_LP64_LIB mkl_intel_lp64 PATHS ENV LIBRARY_PATH)
find_library(MKL_SEQUENTIAL_LIB mkl_sequential PATHS ENV LIBRARY_PATH)
find_library(MKL_CORE_LIB mkl_core PATHS ENV LIBRARY_PATH)
if(NOT (MKL_INTEL_LP64_LIB OR MKL_SEQUENTIAL_LIB OR MKL_CORE_LIB))
message(FATAL_ERROR "Cannot find Intel(R) Math Kernel Library (Intel(R) MKL).")
endif()
add_executable(cholesky init.cpp cholesky.cpp)
target_link_libraries(cholesky
${MKL_INTEL_LP64_LIB}
${MKL_SEQUENTIAL_LIB}
${MKL_CORE_LIB}
TBB::tbb
Threads::Threads
)
target_compile_options(cholesky PRIVATE ${TBB_CXX_STD_FLAG})
set(EXECUTABLE "$<TARGET_FILE:cholesky>")
set(ARGS 4 2)
add_execution_target(run_cholesky cholesky ${EXECUTABLE} "${ARGS}")
+37
View File
@@ -0,0 +1,37 @@
# Cholesky sample
This directory contains an example of several versions of Cholesky Factorization algorithm.
**dpotrf**: An implementation that calls the oneAPI Math Kernel Library (oneMKL) `dpotrf` function to directly perform the factorization. This can be a serial implementation or threaded implementation depending on the version of the oneMKL library that is linked against.
**crout**: A serial implementation that uses the Crout-Cholesky algorithm for factorization. The same approach is parallelized for the other oneAPI Threading Building Blocks (oneTBB) based approaches below.
**depend**: A parallel version of Crout-Cholesky factorization that uses the oneTBB flow graph. This version uses a dependency graph made solely of `continue_node` objects. This an inspector-executor approach, where a loop nest that is similar to the serial implementation is used to create an unrolled version of the computation. Where the oneMKL calls would have been made in the original serial implementation of Crout-Cholesky, graph nodes are created instead and these nodes are linked by edges to the other nodes they are dependent upon. The resulting graph is relatively large, with a node for each instance of each oneMKL call. For example, there are many nodes that call `dtrsm`; one for each invocation of `dtrsm` in the serial implementation. The is very little overhead in message management for this version and so it is often the highest performing.
**join**: A parallel version of Crout-Cholesky factorization that uses the oneTBB flow graph. This version uses a data flow approach. This is a small, compact graph that passes tiles along its edges. There is one node per type of oneMKL call, plus `join_node`s that combine the inputs required for each call. So for example, there is only a single node that applies all calls to `dtrsm`. This node is invoked when the tiles that hold the inputs and outputs for an invocation are matched together in the tag-matching `join_node` that precedes it. The tag represents the iteration values of the `i`, `j`, `k` loops in the serial implementation at that invocation of the call. There is some overhead in message matching and forwarding, so it may not perform as well as the dependency graph implementation.
This sample code requires a oneTBB library and also the oneMKL library.
## Building the example
```
cmake <path_to_example>
cmake --build .
```
## Running the sample
### Predefined make targets
* `make run_cholesky` - executes the example with predefined parameters.
### Application parameters
Usage:
```
cholesky [size=value] [blocksize=value] [num_trials=value] [output_prefix=value] [algorithm=value] [num_tbb_threads=value] [input_file=value] [-x] [-h] [size [blocksize [num_trials [output_prefix [algorithm [num_tbb_threads]]]]]]
```
* `-h` - prints the help for command line options.
* `size` - the row/column size of `NxN` matrix (size <= 46000).
* `blocksize` - the block size; size must be a multiple of the blocksize.
* `num_trials` - the number of times to run each algorithm.
* `output_prefix` - if provided the prefix will be prepended to output files: <output_prefix>_posdef.txt and <output_prefix>_X.txt; where `X` is the algorithm used. If `output_prefix` is not provided, no output will be written.
* `algorithm` - name of the used algorithm - can be dpotrf, crout, depend or join.
* `num_tbb_threads` - number of oneTBB threads.
* `input_file` - input matrix (optional). If omitted, randomly generated values are used.
* `-x` - skips all validation.
+723
View File
@@ -0,0 +1,723 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <tuple>
#include "mkl_lapack.h"
#include "mkl.h"
#include "oneapi/tbb/flow_graph.h"
#include "oneapi/tbb/tick_count.h"
#include "oneapi/tbb/global_control.h"
// Application command line arguments parsing
#include "common/utility/utility.hpp"
#include "common/utility/get_default_num_threads.hpp"
/************************************************************
FORWARD DECLARATIONS
************************************************************/
/**********************************************
Read or generate a positive-definite matrix
-- reads from file if fname != nullptr
-- sets n to matrix size
-- allocates and reads values in to A
-- otherwise generates a matrix
-- uses n to determine size
-- allocates and generates values in to A
**********************************************/
void matrix_init(double *&A, int &n, const char *fname);
/**********************************************
Writes a lower triangular matrix to a file
-- first line of file is n
-- subsequently 1 row per line
**********************************************/
void matrix_write(double *A, int n, const char *fname, bool is_triangular = false);
/************************************************************
GLOBAL VARIABLES
************************************************************/
bool g_benchmark_run = false;
int g_n = -1, g_b = -1, g_num_trials = 1;
char *g_input_file_name = nullptr;
char *g_output_prefix = nullptr;
std::string g_alg_name;
int g_num_tbb_threads;
// Creates tiled array
static double ***create_tile_array(double *A, int n, int b) {
const int p = n / b;
double ***tile = (double ***)calloc(sizeof(double **), p);
for (int j = 0; j < p; ++j) {
tile[j] = (double **)calloc(sizeof(double *), p);
}
for (int j = 0; j < p; ++j) {
for (int i = 0; i < p; ++i) {
double *temp_block = (double *)calloc(sizeof(double), b * b);
for (int A_j = j * b, T_j = 0; T_j < b; ++A_j, ++T_j) {
for (int A_i = i * b, T_i = 0; T_i < b; ++A_i, ++T_i) {
temp_block[T_j * b + T_i] = A[A_j * n + A_i];
}
}
tile[j][i] = temp_block;
}
}
return tile;
}
static void collapse_tile_array(double ***tile, double *A, int n, int b) {
const int p = n / b;
for (int j = 0; j < p; ++j) {
for (int i = 0; i < p; ++i) {
double *temp_block = tile[j][i];
for (int A_j = j * b, T_j = 0; T_j < b; ++A_j, ++T_j) {
for (int A_i = i * b, T_i = 0; T_i < b; ++A_i, ++T_i) {
A[A_j * n + A_i] = temp_block[T_j * b + T_i];
}
}
free(temp_block);
tile[j][i] = nullptr;
}
free(tile[j]);
}
free(tile);
}
/************************************************************
Helper base class: algorithm
************************************************************/
class algorithm {
std::string name;
bool is_tiled;
bool check_if_valid(double *A0, double *C, double *A, int n) {
char transa = 'n', transb = 't';
double alpha = 1;
double beta = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
A0[j * n + i] = 0.;
}
}
dgemm(&transa, &transb, &n, &n, &n, &alpha, A0, &n, A0, &n, &beta, C, &n);
for (int j = 0; j < n; ++j) {
for (int i = 0; i < n; ++i) {
const double epsilon = std::abs(A[j * n + i] * 0.1);
if (std::abs(C[j * n + i] - A[j * n + i]) > epsilon) {
printf("ERROR: %s did not validate at C(%d,%d) = %lf != A(%d,%d) = %lf\n",
name.c_str(),
i,
j,
C[j * n + i],
i,
j,
A[j * n + i]);
printf("ERROR: %g; %g < %g < %g\n",
epsilon,
A[j * n + i] - epsilon,
C[j * n + i],
A[j * n + i] + epsilon);
return false;
}
}
}
return true;
}
public:
algorithm(const std::string &alg_name, bool t) : name(alg_name), is_tiled(t) {}
double operator()(double *A, int n, int b, int trials) {
oneapi::tbb::tick_count t0, t1;
double elapsed_time = 0.0;
double *A0 = (double *)calloc(sizeof(double), n * n);
double *C = (double *)calloc(sizeof(double), n * n);
for (int i = 0; i < trials + 1; ++i) {
if (is_tiled) {
double ***tile = create_tile_array(A, n, b);
t0 = oneapi::tbb::tick_count::now();
func(tile, n, b);
t1 = oneapi::tbb::tick_count::now();
collapse_tile_array(tile, A0, n, b);
}
else {
memcpy(A0, A, sizeof(double) * n * n);
t0 = oneapi::tbb::tick_count::now();
func(A0, n, b);
t1 = oneapi::tbb::tick_count::now();
}
if (i)
elapsed_time += (t1 - t0).seconds();
if (!g_benchmark_run && !check_if_valid(A0, C, A, n)) {
if (g_output_prefix) {
std::string s(g_output_prefix);
s += "_" + name + ".txt";
matrix_write(A0, g_n, s.c_str(), true);
free(A0);
free(C);
return 0.;
}
}
}
if (g_output_prefix) {
std::string s(g_output_prefix);
s += "_" + name + ".txt";
matrix_write(A0, g_n, s.c_str(), true);
}
printf("%s %d %d %d %d %lf %lf\n",
name.c_str(),
g_num_tbb_threads,
trials,
n,
b,
elapsed_time,
elapsed_time / trials);
free(A0);
free(C);
return elapsed_time;
}
protected:
// Main algorithm body function must be defined in any direved class
virtual void func(void *ptr, int n, int b) = 0;
};
/***********************************************************/
static void call_dpotf2(double ***tile, int b, int k) {
double *A_block = tile[k][k];
char uplo = 'l';
int info = 0;
dpotf2(&uplo, &b, A_block, &b, &info);
return;
}
static void call_dtrsm(double ***tile, int b, int k, int j) {
double *A_block = tile[k][j];
double *L_block = tile[k][k];
char uplo = 'l', side = 'r', transa = 't', diag = 'n';
double alpha = 1;
dtrsm(&side, &uplo, &transa, &diag, &b, &b, &alpha, L_block, &b, A_block, &b);
return;
}
static void call_dsyr2k(double ***tile, int b, int k, int j, int i) {
double *A_block = tile[i][j];
char transa = 'n', transb = 't';
char uplo = 'l';
double alpha = -1;
double beta = 1;
if (i == j) { // Diagonal block
double *L_block = tile[k][i];
dsyrk(&uplo, &transa, &b, &b, &alpha, L_block, &b, &beta, A_block, &b);
}
else { // Non-diagonal block
double *L2_block = tile[k][i];
double *L1_block = tile[k][j];
dgemm(&transa, &transb, &b, &b, &b, &alpha, L1_block, &b, L2_block, &b, &beta, A_block, &b);
}
return;
}
class algorithm_crout : public algorithm {
public:
algorithm_crout() : algorithm("crout_cholesky", true) {}
protected:
virtual void func(void *ptr, int n, int b) {
double ***tile = (double ***)ptr;
const int p = n / b;
for (int k = 0; k < p; ++k) {
call_dpotf2(tile, b, k);
for (int j = k + 1; j < p; ++j) {
call_dtrsm(tile, b, k, j);
for (int i = k + 1; i <= j; ++i) {
call_dsyr2k(tile, b, k, j, i);
}
}
}
}
};
class algorithm_dpotrf : public algorithm {
public:
algorithm_dpotrf() : algorithm("dpotrf_cholesky", false) {}
protected:
virtual void func(void *ptr, int n, int /* b */) {
double *A = (double *)ptr;
int lda = n;
int info = 0;
char uplo = 'l';
dpotrf(&uplo, &n, A, &lda, &info);
}
};
/************************************************************
Begin data join graph based version of cholesky
************************************************************/
typedef union {
char a[4];
std::size_t tag;
} tag_t;
typedef double *tile_t;
typedef std::pair<tag_t, tile_t> tagged_tile_t;
typedef std::tuple<tagged_tile_t> t1_t;
typedef std::tuple<tagged_tile_t, tagged_tile_t> t2_t;
typedef std::tuple<tagged_tile_t, tagged_tile_t, tagged_tile_t> t3_t;
typedef oneapi::tbb::flow::multifunction_node<tagged_tile_t, t1_t> dpotf2_node_t;
typedef oneapi::tbb::flow::multifunction_node<t2_t, t2_t> dtrsm_node_t;
typedef oneapi::tbb::flow::multifunction_node<t3_t, t3_t> dsyr2k_node_t;
typedef oneapi::tbb::flow::join_node<t2_t, oneapi::tbb::flow::tag_matching> dtrsm_join_t;
typedef oneapi::tbb::flow::join_node<t3_t, oneapi::tbb::flow::tag_matching> dsyr2k_join_t;
class dpotf2_body {
int p;
int b;
public:
dpotf2_body(int p_, int b_) : p(p_), b(b_) {}
void operator()(const tagged_tile_t &in, dpotf2_node_t::output_ports_type &ports) {
int k = in.first.a[0];
tile_t A_block = in.second;
tag_t t;
t.tag = 0;
t.a[0] = k;
char uplo = 'l';
int info = 0;
dpotf2(&uplo, &b, A_block, &b, &info);
// Send to dtrsms in same column
// k == k j == k
t.a[2] = k;
for (int j = k + 1; j < p; ++j) {
t.a[1] = j;
std::get<0>(ports).try_put(std::make_pair(t, A_block));
}
}
};
class dtrsm_body {
int p;
int b;
public:
dtrsm_body(int p_, int b_) : p(p_), b(b_) {}
void operator()(const t2_t &in, dtrsm_node_t::output_ports_type &ports) {
tagged_tile_t in0 = std::get<0>(in);
tagged_tile_t in1 = std::get<1>(in);
int k = in0.first.a[0];
int j = in0.first.a[1];
tile_t L_block = in0.second;
tile_t A_block = in1.second;
tag_t t;
t.tag = 0;
t.a[0] = k;
char uplo = 'l', side = 'r', transa = 't', diag = 'n';
double alpha = 1;
dtrsm(&side, &uplo, &transa, &diag, &b, &b, &alpha, L_block, &b, A_block, &b);
// Send to rest of my row
t.a[1] = j;
for (int i = k + 1; i <= j; ++i) {
t.a[2] = i;
std::get<0>(ports).try_put(std::make_pair(t, A_block));
}
// Send to transposed row
t.a[2] = j;
for (int i = j; i < p; ++i) {
t.a[1] = i;
std::get<1>(ports).try_put(std::make_pair(t, A_block));
}
}
};
class dsyr2k_body {
int p;
int b;
public:
dsyr2k_body(int p_, int b_) : p(p_), b(b_) {}
void operator()(const t3_t &in, dsyr2k_node_t::output_ports_type &ports) {
tag_t t;
t.tag = 0;
char transa = 'n', transb = 't';
char uplo = 'l';
double alpha = -1;
double beta = 1;
tagged_tile_t in0 = std::get<0>(in);
tagged_tile_t in1 = std::get<1>(in);
tagged_tile_t in2 = std::get<2>(in);
int k = in2.first.a[0];
int j = in2.first.a[1];
int i = in2.first.a[2];
tile_t A_block = in2.second;
if (i == j) { // Diagonal block
tile_t L_block = in0.second;
dsyrk(&uplo, &transa, &b, &b, &alpha, L_block, &b, &beta, A_block, &b);
}
else { // Non-diagonal block
tile_t L1_block = in0.second;
tile_t L2_block = in1.second;
dgemm(&transa,
&transb,
&b,
&b,
&b,
&alpha,
L1_block,
&b,
L2_block,
&b,
&beta,
A_block,
&b);
}
// All outputs flow to next step
t.a[0] = k + 1;
t.a[1] = j;
t.a[2] = i;
if (k != p - 1 && j == k + 1 && i == k + 1) {
std::get<0>(ports).try_put(std::make_pair(t, A_block));
}
if (k < p - 2) {
if (i == k + 1 && j > i) {
t.a[0] = k + 1;
t.a[1] = j;
std::get<1>(ports).try_put(std::make_pair(t, A_block));
}
if (j != k + 1 && i != k + 1) {
t.a[0] = k + 1;
t.a[1] = j;
t.a[2] = i;
std::get<2>(ports).try_put(std::make_pair(t, A_block));
}
}
}
};
struct tagged_tile_to_size_t {
std::size_t operator()(const tagged_tile_t &t) {
return t.first.tag;
}
};
class algorithm_join : public algorithm {
public:
algorithm_join() : algorithm("data_join_cholesky", true) {}
protected:
virtual void func(void *ptr, int n, int b) {
using oneapi::tbb::flow::unlimited;
using oneapi::tbb::flow::output_port;
using oneapi::tbb::flow::input_port;
double ***tile = (double ***)ptr;
const int p = n / b;
oneapi::tbb::flow::graph g;
dpotf2_node_t dpotf2_node(g, unlimited, dpotf2_body(p, b));
dtrsm_node_t dtrsm_node(g, unlimited, dtrsm_body(p, b));
dsyr2k_node_t dsyr2k_node(g, unlimited, dsyr2k_body(p, b));
dtrsm_join_t dtrsm_join(g, tagged_tile_to_size_t(), tagged_tile_to_size_t());
dsyr2k_join_t dsyr2k_join(
g, tagged_tile_to_size_t(), tagged_tile_to_size_t(), tagged_tile_to_size_t());
make_edge(output_port<0>(dsyr2k_node), dpotf2_node);
make_edge(output_port<0>(dpotf2_node), input_port<0>(dtrsm_join));
make_edge(output_port<1>(dsyr2k_node), input_port<1>(dtrsm_join));
make_edge(dtrsm_join, dtrsm_node);
make_edge(output_port<0>(dtrsm_node), input_port<0>(dsyr2k_join));
make_edge(output_port<1>(dtrsm_node), input_port<1>(dsyr2k_join));
make_edge(output_port<2>(dsyr2k_node), input_port<2>(dsyr2k_join));
make_edge(dsyr2k_join, dsyr2k_node);
// Now we need to send out the tiles to their first nodes
tag_t t;
t.tag = 0;
t.a[0] = 0;
t.a[1] = 0;
t.a[2] = 0;
// Send to feedback input of first dpotf2
// k == 0, j == 0, i == 0
dpotf2_node.try_put(std::make_pair(t, tile[0][0]));
// Send to feedback input (port 1) of each dtrsm
// k == 0, j == 1..p-1
for (int j = 1; j < p; ++j) {
t.a[1] = j;
input_port<1>(dtrsm_join).try_put(std::make_pair(t, tile[0][j]));
}
// Send to feedback input (port 2) of each dsyr2k
// k == 0
for (int i = 1; i < p; ++i) {
t.a[2] = i;
for (int j = i; j < p; ++j) {
t.a[1] = j;
input_port<2>(dsyr2k_join).try_put(std::make_pair(t, tile[i][j]));
}
}
g.wait_for_all();
}
};
/************************************************************
End data join graph based version of cholesky
************************************************************/
/************************************************************
Begin dependence graph based version of cholesky
************************************************************/
typedef oneapi::tbb::flow::continue_node<oneapi::tbb::flow::continue_msg> continue_type;
typedef continue_type *continue_ptr_type;
class algorithm_depend : public algorithm {
public:
algorithm_depend() : algorithm("depend_cholesky", true) {}
protected:
virtual void func(void *ptr, int n, int b) {
double ***tile = (double ***)ptr;
const int p = n / b;
continue_ptr_type *c = new continue_ptr_type[p];
continue_ptr_type **t = new continue_ptr_type *[p];
continue_ptr_type ***u = new continue_ptr_type **[p];
oneapi::tbb::flow::graph g;
for (int k = p - 1; k >= 0; --k) {
c[k] = new continue_type(g, [=](const oneapi::tbb::flow::continue_msg &) {
call_dpotf2(tile, b, k);
});
t[k] = new continue_ptr_type[p];
u[k] = new continue_ptr_type *[p];
for (int j = k + 1; j < p; ++j) {
t[k][j] = new continue_type(g, [=](const oneapi::tbb::flow::continue_msg &) {
call_dtrsm(tile, b, k, j);
});
make_edge(*c[k], *t[k][j]);
u[k][j] = new continue_ptr_type[p];
for (int i = k + 1; i <= j; ++i) {
u[k][j][i] = new continue_type(g, [=](const oneapi::tbb::flow::continue_msg &) {
call_dsyr2k(tile, b, k, j, i);
});
if (k < p - 2 && k + 1 != j && k + 1 != i) {
make_edge(*u[k][j][i], *u[k + 1][j][i]);
}
make_edge(*t[k][j], *u[k][j][i]);
if (i != j) {
make_edge(*t[k][i], *u[k][j][i]);
}
if (k < p - 2 && j > i && i == k + 1) {
make_edge(*u[k][j][i], *t[i][j]);
}
}
}
if (k != p - 1) {
make_edge(*u[k][k + 1][k + 1], *c[k + 1]);
}
}
c[0]->try_put(oneapi::tbb::flow::continue_msg());
g.wait_for_all();
for (int k = p - 1; k >= 0; --k) {
for (int j = k + 1; j < p; ++j) {
for (int i = k + 1; i <= j; ++i) {
delete u[k][j][i];
}
delete t[k][j];
delete[] u[k][j];
}
delete c[k];
delete[] t[k];
delete[] u[k];
}
delete[] c;
delete[] t;
delete[] u;
}
}; // class algorithm_depend
/************************************************************
End dependence graph based version of cholesky
************************************************************/
bool process_args(int argc, char *argv[]) {
utility::parse_cli_arguments(
argc,
argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.positional_arg(g_n, "size", "the row/column size of NxN matrix (size <= 46000)")
.positional_arg(
g_b, "blocksize", "the block size; size must be a multiple of the blocksize")
.positional_arg(g_num_trials, "num_trials", "the number of times to run each algorithm")
.positional_arg(
g_output_prefix,
"output_prefix",
"if provided the prefix will be preappended to output files:\n"
" output_prefix_posdef.txt\n"
" output_prefix_X.txt; where X is the algorithm used\n"
" if output_prefix is not provided, no output will be written")
.positional_arg(g_alg_name,
"algorithm",
"name of the used algorithm - can be dpotrf, crout, depend or join")
.positional_arg(g_num_tbb_threads, "num_tbb_threads", "number of started TBB threads")
.arg(g_input_file_name,
"input_file",
"if provided it will be read to get the input matrix")
.arg(g_benchmark_run, "-x", "skips all validation"));
if (g_n > 46000) {
printf("ERROR: invalid 'size' value (must be less or equal 46000): %d\n", g_n);
return false;
}
if (g_n % g_b != 0) {
printf("ERROR: size %d must be a multiple of the blocksize %d\n", g_n, g_b);
return false;
}
if (g_n / g_b > 256) {
// Because tile index size is 1 byte only in tag_t type
printf("ERROR: size / blocksize must be less or equal 256, but %d / %d = %d\n",
g_n,
g_b,
g_n / g_b);
return false;
}
if (g_b == -1 || (g_n == -1 && g_input_file_name == nullptr)) {
return false;
}
return true;
}
int main(int argc, char *argv[]) {
g_num_tbb_threads = utility::get_default_num_threads();
typedef std::map<std::string, algorithm *> algmap_t;
algmap_t algmap;
// Init algorithms
algmap.insert(std::pair<std::string, algorithm *>("dpotrf", new algorithm_dpotrf));
algmap.insert(std::pair<std::string, algorithm *>("crout", new algorithm_crout));
algmap.insert(std::pair<std::string, algorithm *>("depend", new algorithm_depend));
algmap.insert(std::pair<std::string, algorithm *>("join", new algorithm_join));
if (!process_args(argc, argv)) {
printf("ERROR: Invalid arguments. Run: %s -h\n", argv[0]);
return -1;
}
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
g_num_tbb_threads);
double *A = nullptr;
// Read input matrix
matrix_init(A, g_n, g_input_file_name);
// Write input matrix if output_prefix is set and we didn't read from a file
if (!g_input_file_name && g_output_prefix) {
std::string s(g_output_prefix);
s += "_posdef.txt";
matrix_write(A, g_n, s.c_str());
}
if (g_alg_name.empty()) {
for (algmap_t::iterator i = algmap.begin(); i != algmap.end(); ++i) {
algorithm *const alg = i->second;
(*alg)(A, g_n, g_b, g_num_trials);
}
}
else {
algmap_t::iterator alg_iter = algmap.find(g_alg_name);
if (alg_iter != algmap.end()) {
algorithm *const alg = alg_iter->second;
(*alg)(A, g_n, g_b, g_num_trials);
}
else {
printf("ERROR: Invalid algorithm name: %s\n", g_alg_name.c_str());
return -1;
}
}
free(A);
return 0;
}
+136
View File
@@ -0,0 +1,136 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <mkl_cblas.h>
static void posdef_gen(double *A, int n) {
/* Allocate memory for the matrix and its transpose */
double *L = (double *)calloc(sizeof(double), n * n);
assert(L);
double *LT = (double *)calloc(sizeof(double), n * n);
assert(LT);
memset(A, 0, sizeof(double) * n * n);
/* Generate a conditioned matrix and fill it with random numbers */
for (int j = 0; j < n; ++j) {
for (int k = 0; k < j; ++k) {
// The initial value has to be between [0,1].
L[k * n + j] =
(((j * k) / ((double)(j + 1)) / ((double)(k + 2)) * 2.0) - 1.0) / ((double)n);
}
L[j * n + j] = 1;
}
/* Compute transpose of the matrix */
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
LT[j * n + i] = L[i * n + j];
}
}
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans, n, n, n, 1, L, n, LT, n, 0, A, n);
free(L);
free(LT);
}
// Read the matrix from the input file
void matrix_init(double *&A, int &n, const char *fname) {
if (fname) {
int i;
int j;
FILE *fp;
fp = fopen(fname, "r");
if (fp == nullptr) {
fprintf(stderr, "\nFile does not exist\n");
std::exit(0);
}
if (fscanf(fp, "%d", &n) <= 0) {
fprintf(stderr, "\nCouldn't read n from %s\n", fname);
std::exit(-1);
}
A = (double *)calloc(sizeof(double), n * n);
for (i = 0; i < n; ++i) {
for (j = 0; j <= i; ++j) {
if (fscanf(fp, "%lf ", &A[i * n + j]) <= 0) {
fprintf(stderr, "\nMatrix size incorrect %i %i\n", i, j);
std::exit(-1);
}
if (i != j) {
A[j * n + i] = A[i * n + j];
}
}
}
fclose(fp);
}
else {
A = (double *)calloc(sizeof(double), n * n);
posdef_gen(A, n);
}
}
// write matrix to file
void matrix_write(double *A, int n, const char *fname, bool is_triangular = false) {
if (fname) {
int i = 0;
int j = 0;
FILE *fp = nullptr;
fp = fopen(fname, "w");
if (fp == nullptr) {
fprintf(stderr, "\nCould not open file %s for writing.\n", fname);
std::exit(0);
}
fprintf(fp, "%d\n", n);
for (i = 0; i < n; ++i) {
for (j = 0; j <= i; ++j) {
fprintf(fp, "%lf ", A[j * n + i]);
}
if (!is_triangular) {
for (; j < n; ++j) {
fprintf(fp, "%lf ", A[i * n + j]);
}
}
else {
for (; j < n; ++j) {
fprintf(fp, "%lf ", 0.0);
}
}
fprintf(fp, "\n");
}
if (is_triangular) {
fprintf(fp, "\n");
for (i = 0; i < n; ++i) {
for (j = 0; j < i; ++j) {
fprintf(fp, "%lf ", 0.0);
}
for (; j < n; ++j) {
fprintf(fp, "%lf ", A[i * n + j]);
}
fprintf(fp, "\n");
}
}
fclose(fp);
}
}
@@ -0,0 +1,33 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(dining_philosophers CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
add_executable(dining_philosophers dining_philosophers.cpp)
target_link_libraries(dining_philosophers TBB::tbb Threads::Threads)
target_compile_options(dining_philosophers PRIVATE ${TBB_CXX_STD_FLAG})
set(EXECUTABLE "$<TARGET_FILE:dining_philosophers>")
set(ARGS auto 5)
set(LIGHT_ARGS auto 3)
add_execution_target(run_dining_philosophers dining_philosophers ${EXECUTABLE} "${ARGS}")
add_execution_target(light_test_dining_philosophers dining_philosophers ${EXECUTABLE} "${LIGHT_ARGS}")
@@ -0,0 +1,25 @@
# Dining_philosophers sample
The Dining Philosophers problem demonstrates `oneapi::tbb::flow` and the use of the reserving `join_node` to solve the potential deadlock.
This program runs some number of philosophers in parallel, each thinking and then waiting for chopsticks to be available before eating. Eating and thinking are implemented with `sleep()`. The chopstick positions are represented by a `queue_node` with one item.
## Building the example
```
cmake <path_to_example>
cmake --build .
```
## Running the sample
### Predefined make targets
* `make run_dining_philosophers` - executes the example with predefined parameters.
* `make light_test_dining_philosophers` - executes the example with suggested parameters to reduce execution time.
### Application parameters
Usage:
```
dining_philosophers [n-of_threads=value] [n-of-philosophers=value] [verbose] [-h] [n-of_threads [n-of-philosophers]]
```
* `-h` - prints the help for command line options.
* `n-of_threads` - number of threads to use; a range of the form low\[:high\[:(+|*|#)step\]\], where low and optional high are non-negative integers or 'auto' for the default choice, and optional step expression specifies how thread numbers are chosen within the range.
* `n-of-philosophers` - how many philosophers, from 2-26.
* `verbose` - prints diagnostic output to screen.
@@ -0,0 +1,335 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#if _MSC_VER
// Suppress "decorated name length exceeded, name was truncated" warning
#pragma warning(disable : 4503)
#endif
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <thread>
#include <chrono>
#include <tuple>
#include "oneapi/tbb/flow_graph.h"
#include "oneapi/tbb/tick_count.h"
#include "oneapi/tbb/spin_mutex.h"
#include "oneapi/tbb/global_control.h"
#include "common/utility/utility.hpp"
#include "common/utility/get_default_num_threads.hpp"
// Each philosopher is an object, and is invoked in the think() function_node, the
// eat() function_node and forward() multifunction_node.
//
// The graph is constructed, and each think() function_node is started with a continue_msg.
//
// The philosopher will think, then gather two chopsticks, eat, place the chopsticks back,
// and if they have not completed the required number of cycles, will start to think() again
// by sending a continue_msg to their corresponding think() function_node.
//
// The reserving join has as its inputs the left and right chopstick queues an a queue
// that stores the continue_msg emitted by the function_node after think()ing is done.
// When all three inputs are available, a tuple of the inputs will be forwarded to the
// eat() function_node. The output of the eat() function_node is sent to the forward()
// multifunction_node.
const std::chrono::seconds think_time(1);
const std::chrono::seconds eat_time(1);
const int num_times = 10;
oneapi::tbb::tick_count t0;
bool verbose = false;
const char *names[] = { "Archimedes", "Bakunin", "Confucius", "Democritus", "Euclid",
"Favorinus", "Geminus", "Heraclitus", "Ichthyas", "Jason of Nysa",
"Kant", "Lavrov", "Metrocles", "Nausiphanes", "Onatas",
"Phaedrus", "Quillot", "Russell", "Socrates", "Thales",
"Udayana", "Vernadsky", "Wittgenstein", "Xenophilus", "Yen Yuan",
"Zenodotus" };
const int NumPhilosophers = sizeof(names) / sizeof(char *);
struct RunOptions {
utility::thread_number_range threads;
int number_of_philosophers;
bool silent;
RunOptions(utility::thread_number_range threads_, int number_of_philosophers_, bool silent_)
: threads(threads_),
number_of_philosophers(number_of_philosophers_),
silent(silent_) {}
};
RunOptions ParseCommandLine(int argc, char *argv[]) {
int auto_threads = utility::get_default_num_threads();
utility::thread_number_range threads(
utility::get_default_num_threads, auto_threads, auto_threads);
int nPhilosophers = 5;
bool verbose = false;
char charbuf[100];
std::sprintf(charbuf, "%d", NumPhilosophers);
std::string pCount = "how many philosophers, from 2-";
pCount += charbuf;
utility::cli_argument_pack cli_pack;
cli_pack.positional_arg(threads, "n-of_threads", utility::thread_number_range_desc)
.positional_arg(nPhilosophers, "n-of-philosophers", pCount)
.arg(verbose, "verbose", "verbose output");
utility::parse_cli_arguments(argc, argv, cli_pack);
if (nPhilosophers < 2 || nPhilosophers > NumPhilosophers) {
std::cout << "Number of philosophers (" << nPhilosophers
<< ") out of range [2:" << NumPhilosophers << "]\n";
std::cout << cli_pack.usage_string(argv[0]) << std::flush;
std::exit(-1);
}
return RunOptions(threads, nPhilosophers, !verbose);
}
oneapi::tbb::spin_mutex my_mutex;
class chopstick {};
typedef std::tuple<oneapi::tbb::flow::continue_msg, chopstick, chopstick> join_output;
typedef oneapi::tbb::flow::join_node<join_output, oneapi::tbb::flow::reserving> join_node_type;
typedef oneapi::tbb::flow::function_node<oneapi::tbb::flow::continue_msg,
oneapi::tbb::flow::continue_msg>
think_node_type;
typedef oneapi::tbb::flow::function_node<join_output, oneapi::tbb::flow::continue_msg>
eat_node_type;
typedef oneapi::tbb::flow::multifunction_node<oneapi::tbb::flow::continue_msg, join_output>
forward_node_type;
class philosopher {
public:
philosopher(const char *name) : my_name(name), my_count(num_times) {}
~philosopher() {}
void check();
const char *name() const {
return my_name;
}
private:
friend std::ostream &operator<<(std::ostream &o, philosopher const &p);
const char *my_name;
int my_count;
friend class think_node_body;
friend class eat_node_body;
friend class forward_node_body;
void think();
void eat();
void forward(const oneapi::tbb::flow::continue_msg &in,
forward_node_type::output_ports_type &out_ports);
};
std::ostream &operator<<(std::ostream &o, philosopher const &p) {
o << "< philosopher[" << reinterpret_cast<uintptr_t>(const_cast<philosopher *>(&p)) << "] "
<< p.name() << ", my_count=" << p.my_count;
return o;
}
class think_node_body {
philosopher &my_philosopher;
public:
think_node_body(philosopher &p) : my_philosopher(p) {}
think_node_body(const think_node_body &other) : my_philosopher(other.my_philosopher) {}
oneapi::tbb::flow::continue_msg operator()(oneapi::tbb::flow::continue_msg /*m*/) {
my_philosopher.think();
return oneapi::tbb::flow::continue_msg();
}
};
class eat_node_body {
philosopher &my_philosopher;
public:
eat_node_body(philosopher &p) : my_philosopher(p) {}
eat_node_body(const eat_node_body &other) : my_philosopher(other.my_philosopher) {}
oneapi::tbb::flow::continue_msg operator()(const join_output &in) {
my_philosopher.eat();
return oneapi::tbb::flow::continue_msg();
}
};
class forward_node_body {
philosopher &my_philosopher;
public:
forward_node_body(philosopher &p) : my_philosopher(p) {}
forward_node_body(const forward_node_body &other) : my_philosopher(other.my_philosopher) {}
void operator()(const oneapi::tbb::flow::continue_msg &in,
forward_node_type::output_ports_type &out) {
my_philosopher.forward(in, out);
}
};
void philosopher::check() {
if (my_count != 0) {
std::printf("ERROR: philosopher %s still had to run %d more times\n", name(), my_count);
std::exit(-1);
}
}
void philosopher::forward(const oneapi::tbb::flow::continue_msg & /*in*/,
forward_node_type::output_ports_type &out_ports) {
if (my_count < 0)
abort();
--my_count;
(void)std::get<1>(out_ports).try_put(chopstick());
(void)std::get<2>(out_ports).try_put(chopstick());
if (my_count > 0) {
(void)std::get<0>(out_ports).try_put(
oneapi::tbb::flow::continue_msg()); //start thinking again
}
else {
if (verbose) {
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
std::printf("%s has left the building\n", name());
}
}
}
void philosopher::eat() {
if (verbose) {
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
std::printf("%s eating\n", name());
}
std::this_thread::sleep_for(eat_time);
if (verbose) {
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
std::printf("%s done eating\n", name());
}
}
void philosopher::think() {
if (verbose) {
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
std::printf("%s thinking\n", name());
}
std::this_thread::sleep_for(think_time);
if (verbose) {
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
std::printf("%s done thinking\n", name());
}
}
typedef oneapi::tbb::flow::queue_node<oneapi::tbb::flow::continue_msg> thinking_done_type;
int main(int argc, char *argv[]) {
using oneapi::tbb::flow::make_edge;
using oneapi::tbb::flow::input_port;
using oneapi::tbb::flow::output_port;
oneapi::tbb::tick_count main_time = oneapi::tbb::tick_count::now();
int num_threads;
int num_philosophers;
RunOptions options = ParseCommandLine(argc, argv);
num_philosophers = options.number_of_philosophers;
verbose = !options.silent;
for (num_threads = options.threads.first; num_threads <= options.threads.last;
num_threads = options.threads.step(num_threads)) {
oneapi::tbb::global_control c(oneapi::tbb::global_control::max_allowed_parallelism,
num_threads);
oneapi::tbb::flow::graph g;
if (verbose) {
std::cout << "\n"
<< num_philosophers << " philosophers with " << num_threads << " threads"
<< "\n"
<< "\n";
}
t0 = oneapi::tbb::tick_count::now();
std::vector<oneapi::tbb::flow::queue_node<chopstick>> places(
num_philosophers, oneapi::tbb::flow::queue_node<chopstick>(g));
std::vector<philosopher> philosophers;
philosophers.reserve(num_philosophers);
std::vector<think_node_type *> think_nodes;
think_nodes.reserve(num_philosophers);
std::vector<thinking_done_type> done_vector(num_philosophers, thinking_done_type(g));
std::vector<join_node_type> join_vector(num_philosophers, join_node_type(g));
std::vector<eat_node_type *> eat_nodes;
eat_nodes.reserve(num_philosophers);
std::vector<forward_node_type *> forward_nodes;
forward_nodes.reserve(num_philosophers);
for (int i = 0; i < num_philosophers; ++i) {
places[i].try_put(chopstick());
philosophers.push_back(
philosopher(names[i])); // allowed because of default generated assignment
if (verbose) {
oneapi::tbb::spin_mutex::scoped_lock lock(my_mutex);
std::cout << "Built philosopher " << philosophers[i] << "\n";
}
think_nodes.push_back(new think_node_type(
g, oneapi::tbb::flow::unlimited, think_node_body(philosophers[i])));
eat_nodes.push_back(
new eat_node_type(g, oneapi::tbb::flow::unlimited, eat_node_body(philosophers[i])));
forward_nodes.push_back(new forward_node_type(
g, oneapi::tbb::flow::unlimited, forward_node_body(philosophers[i])));
}
// attach chopstick buffers and think function_nodes to joins
for (int i = 0; i < num_philosophers; ++i) {
make_edge(*think_nodes[i], done_vector[i]);
make_edge(done_vector[i], input_port<0>(join_vector[i]));
make_edge(places[i], input_port<1>(join_vector[i])); // left chopstick
make_edge(places[(i + 1) % num_philosophers],
input_port<2>(join_vector[i])); // right chopstick
make_edge(join_vector[i], *eat_nodes[i]);
make_edge(*eat_nodes[i], *forward_nodes[i]);
make_edge(output_port<0>(*forward_nodes[i]), *think_nodes[i]);
make_edge(output_port<1>(*forward_nodes[i]), places[i]);
make_edge(output_port<2>(*forward_nodes[i]), places[(i + 1) % num_philosophers]);
}
// start all the philosophers thinking
for (int i = 0; i < num_philosophers; ++i)
think_nodes[i]->try_put(oneapi::tbb::flow::continue_msg());
g.wait_for_all();
oneapi::tbb::tick_count t1 = oneapi::tbb::tick_count::now();
if (verbose)
std::cout << "\n"
<< num_philosophers << " philosophers with " << num_threads
<< " threads have taken " << (t1 - t0).seconds() << "seconds"
<< "\n";
for (int i = 0; i < num_philosophers; ++i)
philosophers[i].check();
for (int i = 0; i < num_philosophers; ++i) {
delete think_nodes[i];
delete eat_nodes[i];
delete forward_nodes[i];
}
}
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - main_time).seconds());
return 0;
}
+53
View File
@@ -0,0 +1,53 @@
# Copyright (c) 2020-2021 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.1)
project(fgbzip2 CXX)
include(../../common/cmake/common.cmake)
set_common_project_settings(tbb)
add_executable(fgbzip2
blocksort.cpp
bzlib.cpp
compress.cpp
crctable.cpp
decompress.cpp
fgbzip2.cpp
huffman.cpp
randtable.cpp
)
target_link_libraries(fgbzip2 TBB::tbb Threads::Threads)
target_compile_options(fgbzip2 PRIVATE ${TBB_CXX_STD_FLAG})
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL IntelLLVM)
target_compile_options(fgbzip2 PRIVATE -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
endif()
if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Intel)
if (COMMAND target_link_options)
target_link_options(fgbzip2 PRIVATE /FORCE:MULTIPLE /INCREMENTAL:NO)
else()
set_target_properties(fgbzip2 PROPERTIES LINK_FLAGS /FORCE:MULTIPLE /INCREMENTAL:NO)
endif()
endif()
set(EXECUTABLE "$<TARGET_FILE:fgbzip2>")
set(ARGS -b=9 -async "$<TARGET_FILE:fgbzip2>")
add_execution_target(run_fgbzip2 fgbzip2 ${EXECUTABLE} "${ARGS}")
add_execution_target(perf_run_fgbzip2 fgbzip2 ${EXECUTABLE} "${ARGS}")
+28
View File
@@ -0,0 +1,28 @@
# fgbzip2 sample
fgbzip2 is a parallel implementation of bzip2 block-sorting file compressor that uses `oneapi::tbb::flow`. The output of this application is fully compatible with bzip2 v1.0.6 or newer.
This example includes software developed by Julian R Seward. See here for copyright information.
It exemplifies support for asynchronous capabilities in the flow graph API.
## Building the example
```
cmake <path_to_example>
cmake --build .
```
## Running the sample
### Predefined make targets
* `make run_fgbzip2` - executes the example with predefined parameters.
* `make perf_run_fgbzip2` - executes the example with suggested parameters to measure the oneTBB performance.
### Application parameters
Usage:
```
fgbzip2 [-b=value] [-v] [-l=value] [-async] [filename=value] [-h] [filename]
```
* `-h` - prints the help for command line options.
* `-b` - block size in 100 KB chunks, [1 .. 9].
* `-v` - prints diagnostic output to screen.
* `-l` - use memory limit for compression algorithm with 1 MB (minimum) granularity.
* `-async` - use graph `async_node`-based implementation.
* `filename` - name of the file to compress.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+246
View File
@@ -0,0 +1,246 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Public header file for the library. ---*/
/*--- bzlib.h ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
#ifndef _BZLIB_H
#define _BZLIB_H
#ifdef __cplusplus
extern "C" {
#endif
#define BZ_RUN 0
#define BZ_FLUSH 1
#define BZ_FINISH 2
#define BZ_OK 0
#define BZ_RUN_OK 1
#define BZ_FLUSH_OK 2
#define BZ_FINISH_OK 3
#define BZ_STREAM_END 4
#define BZ_SEQUENCE_ERROR (-1)
#define BZ_PARAM_ERROR (-2)
#define BZ_MEM_ERROR (-3)
#define BZ_DATA_ERROR (-4)
#define BZ_DATA_ERROR_MAGIC (-5)
#define BZ_IO_ERROR (-6)
#define BZ_UNEXPECTED_EOF (-7)
#define BZ_OUTBUFF_FULL (-8)
#define BZ_CONFIG_ERROR (-9)
typedef struct {
char* next_in;
unsigned int avail_in;
unsigned int total_in_lo32;
unsigned int total_in_hi32;
char* next_out;
unsigned int avail_out;
unsigned int total_out_lo32;
unsigned int total_out_hi32;
void* state;
void* (*bzalloc)(void*, int, int);
void (*bzfree)(void*, void*);
void* opaque;
} bz_stream;
#ifndef BZ_IMPORT
#define BZ_EXPORT
#endif
#ifndef BZ_NO_STDIO
/* Need a definitition for FILE */
#include <stdio.h>
#endif
#ifdef _WIN32
#include <windows.h>
#ifdef small
/* windows.h define small to char */
#undef small
#endif
#ifdef BZ_EXPORT
#define BZ_API(func) WINAPI func
#define BZ_EXTERN extern
#else
/* import windows dll dynamically */
#define BZ_API(func) (WINAPI * func)
#define BZ_EXTERN
#endif
#else
#define BZ_API(func) func
#define BZ_EXTERN extern
#endif
/*-- Core (low-level) library functions --*/
BZ_EXTERN int BZ_API(BZ2_bzCompressInit)(bz_stream* strm,
int blockSize100k,
int verbosity,
int workFactor);
BZ_EXTERN int BZ_API(BZ2_bzCompress)(bz_stream* strm, int action);
BZ_EXTERN int BZ_API(BZ2_bzCompressEnd)(bz_stream* strm);
BZ_EXTERN int BZ_API(BZ2_bzDecompressInit)(bz_stream* strm, int verbosity, int small);
BZ_EXTERN int BZ_API(BZ2_bzDecompress)(bz_stream* strm);
BZ_EXTERN int BZ_API(BZ2_bzDecompressEnd)(bz_stream* strm);
/*-- High(er) level library functions --*/
#ifndef BZ_NO_STDIO
#define BZ_MAX_UNUSED 5000
typedef void BZFILE;
BZ_EXTERN BZFILE* BZ_API(
BZ2_bzReadOpen)(int* bzerror, FILE* f, int verbosity, int small, void* unused, int nUnused);
BZ_EXTERN void BZ_API(BZ2_bzReadClose)(int* bzerror, BZFILE* b);
BZ_EXTERN void BZ_API(BZ2_bzReadGetUnused)(int* bzerror, BZFILE* b, void** unused, int* nUnused);
BZ_EXTERN int BZ_API(BZ2_bzRead)(int* bzerror, BZFILE* b, void* buf, int len);
BZ_EXTERN BZFILE* BZ_API(
BZ2_bzWriteOpen)(int* bzerror, FILE* f, int blockSize100k, int verbosity, int workFactor);
BZ_EXTERN void BZ_API(BZ2_bzWrite)(int* bzerror, BZFILE* b, void* buf, int len);
BZ_EXTERN void BZ_API(BZ2_bzWriteClose)(int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in,
unsigned int* nbytes_out);
BZ_EXTERN void BZ_API(BZ2_bzWriteClose64)(int* bzerror,
BZFILE* b,
int abandon,
unsigned int* nbytes_in_lo32,
unsigned int* nbytes_in_hi32,
unsigned int* nbytes_out_lo32,
unsigned int* nbytes_out_hi32);
#endif
/*-- Utility functions --*/
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffCompress)(char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int blockSize100k,
int verbosity,
int workFactor);
BZ_EXTERN int BZ_API(BZ2_bzBuffToBuffDecompress)(char* dest,
unsigned int* destLen,
char* source,
unsigned int sourceLen,
int small,
int verbosity);
/*--
Code contributed by Yoshioka Tsuneo (tsuneo@rr.iij4u.or.jp)
to support better zlib compatibility.
This code is not _officially_ part of libbzip2 (yet);
I haven't tested it, documented it, or considered the
threading-safeness of it.
If this code breaks, please contact both Yoshioka and me.
--*/
BZ_EXTERN const char* BZ_API(BZ2_bzlibVersion)(void);
#ifndef BZ_NO_STDIO
BZ_EXTERN BZFILE* BZ_API(BZ2_bzopen)(const char* path, const char* mode);
BZ_EXTERN BZFILE* BZ_API(BZ2_bzdopen)(int fd, const char* mode);
BZ_EXTERN int BZ_API(BZ2_bzread)(BZFILE* b, void* buf, int len);
BZ_EXTERN int BZ_API(BZ2_bzwrite)(BZFILE* b, void* buf, int len);
BZ_EXTERN int BZ_API(BZ2_bzflush)(BZFILE* b);
BZ_EXTERN void BZ_API(BZ2_bzclose)(BZFILE* b);
BZ_EXTERN const char* BZ_API(BZ2_bzerror)(BZFILE* b, int* errnum);
#endif
#ifdef __cplusplus
}
#endif
#endif
/*-------------------------------------------------------------*/
/*--- end bzlib.h ---*/
/*-------------------------------------------------------------*/
+528
View File
@@ -0,0 +1,528 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Private header file for the library. ---*/
/*--- bzlib_private.h ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
#ifndef _BZLIB_PRIVATE_H
#define _BZLIB_PRIVATE_H
#include <cstdlib>
#ifndef BZ_NO_STDIO
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#endif
#include "bzlib.hpp"
/*-- General stuff. --*/
#define BZ_VERSION "1.0.6, 6-Sept-2010"
typedef char Char;
typedef unsigned char Bool;
typedef unsigned char UChar;
typedef int Int32;
typedef unsigned int UInt32;
typedef short Int16;
typedef unsigned short UInt16;
#define True ((Bool)1)
#define False ((Bool)0)
#ifndef __GNUC__
#define __inline__ /* */
#endif
#ifndef BZ_NO_STDIO
extern void BZ2_bz__AssertH__fail(int errcode);
#define AssertH(cond, errcode) \
{ \
if (!(cond)) \
BZ2_bz__AssertH__fail(errcode); \
}
#if BZ_DEBUG
#define AssertD(cond, msg) \
{ \
if (!(cond)) { \
fprintf(stderr, "\n\nlibbzip2(debug build): internal error\n\t%s\n", msg); \
std::exit(-1); \
} \
}
#else
#define AssertD(cond, msg) /* */
#endif
#define VPrintf0(zf) fprintf(stderr, zf)
#define VPrintf1(zf, za1) fprintf(stderr, zf, za1)
#define VPrintf2(zf, za1, za2) fprintf(stderr, zf, za1, za2)
#define VPrintf3(zf, za1, za2, za3) fprintf(stderr, zf, za1, za2, za3)
#define VPrintf4(zf, za1, za2, za3, za4) fprintf(stderr, zf, za1, za2, za3, za4)
#define VPrintf5(zf, za1, za2, za3, za4, za5) fprintf(stderr, zf, za1, za2, za3, za4, za5)
#else
extern void bz_internal_error(int errcode);
#define AssertH(cond, errcode) \
{ \
if (!(cond)) \
bz_internal_error(errcode); \
}
#define AssertD(cond, msg) \
do { \
} while (0)
#define VPrintf0(zf) \
do { \
} while (0)
#define VPrintf1(zf, za1) \
do { \
} while (0)
#define VPrintf2(zf, za1, za2) \
do { \
} while (0)
#define VPrintf3(zf, za1, za2, za3) \
do { \
} while (0)
#define VPrintf4(zf, za1, za2, za3, za4) \
do { \
} while (0)
#define VPrintf5(zf, za1, za2, za3, za4, za5) \
do { \
} while (0)
#endif
#define BZALLOC(nnn) (strm->bzalloc)(strm->opaque, (nnn), 1)
#define BZFREE(ppp) (strm->bzfree)(strm->opaque, (ppp))
/*-- Header bytes. --*/
#define BZ_HDR_B 0x42 /* 'B' */
#define BZ_HDR_Z 0x5a /* 'Z' */
#define BZ_HDR_h 0x68 /* 'h' */
#define BZ_HDR_0 0x30 /* '0' */
/*-- Constants for the back end. --*/
#define BZ_MAX_ALPHA_SIZE 258
#define BZ_MAX_CODE_LEN 23
#define BZ_RUNA 0
#define BZ_RUNB 1
#define BZ_N_GROUPS 6
#define BZ_G_SIZE 50
#define BZ_N_ITERS 4
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
/*-- Stuff for randomising repetitive blocks. --*/
extern Int32 BZ2_rNums[512];
#define BZ_RAND_DECLS \
Int32 rNToGo; \
Int32 rTPos
#define BZ_RAND_INIT_MASK \
s->rNToGo = 0; \
s->rTPos = 0
#define BZ_RAND_MASK ((s->rNToGo == 1) ? 1 : 0)
#define BZ_RAND_UPD_MASK \
if (s->rNToGo == 0) { \
s->rNToGo = BZ2_rNums[s->rTPos]; \
s->rTPos++; \
if (s->rTPos == 512) \
s->rTPos = 0; \
} \
s->rNToGo--;
/*-- Stuff for doing CRCs. --*/
extern UInt32 BZ2_crc32Table[256];
#define BZ_INITIALISE_CRC(crcVar) \
{ crcVar = 0xffffffffL; }
#define BZ_FINALISE_CRC(crcVar) \
{ crcVar = ~(crcVar); }
#define BZ_UPDATE_CRC(crcVar, cha) \
{ crcVar = (crcVar << 8) ^ BZ2_crc32Table[(crcVar >> 24) ^ ((UChar)cha)]; }
/*-- States and modes for compression. --*/
#define BZ_M_IDLE 1
#define BZ_M_RUNNING 2
#define BZ_M_FLUSHING 3
#define BZ_M_FINISHING 4
#define BZ_S_OUTPUT 1
#define BZ_S_INPUT 2
#define BZ_N_RADIX 2
#define BZ_N_QSORT 12
#define BZ_N_SHELL 18
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
/*-- Structure holding all the compression-side stuff. --*/
typedef struct {
/* pointer back to the struct bz_stream */
bz_stream* strm;
/* mode this stream is in, and whether inputting */
/* or outputting data */
Int32 mode;
Int32 state;
/* remembers avail_in when flush/finish requested */
UInt32 avail_in_expect;
/* for doing the block sorting */
UInt32* arr1;
UInt32* arr2;
UInt32* ftab;
Int32 origPtr;
/* aliases for arr1 and arr2 */
UInt32* ptr;
UChar* block;
UInt16* mtfv;
UChar* zbits;
/* for deciding when to use the fallback sorting algorithm */
Int32 workFactor;
/* run-length-encoding of the input */
UInt32 state_in_ch;
Int32 state_in_len;
BZ_RAND_DECLS;
/* input and output limits and current posns */
Int32 nblock;
Int32 nblockMAX;
Int32 numZ;
Int32 state_out_pos;
/* map of bytes used in block */
Int32 nInUse;
Bool inUse[256];
UChar unseqToSeq[256];
/* the buffer for bit stream creation */
UInt32 bsBuff;
Int32 bsLive;
/* block and combined CRCs */
UInt32 blockCRC;
UInt32 combinedCRC;
/* misc administratium */
Int32 verbosity;
Int32 blockNo;
Int32 blockSize100k;
/* stuff for coding the MTF values */
Int32 nMTF;
Int32 mtfFreq[BZ_MAX_ALPHA_SIZE];
UChar selector[BZ_MAX_SELECTORS];
UChar selectorMtf[BZ_MAX_SELECTORS];
UChar len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
/* second dimension: only 3 needed; 4 makes index calculations faster */
UInt32 len_pack[BZ_MAX_ALPHA_SIZE][4];
} EState;
/*-- externs for compression. --*/
extern void BZ2_blockSort(EState*);
extern void BZ2_compressBlock(EState*, Bool);
extern void BZ2_bsInitWrite(EState*);
extern void BZ2_hbAssignCodes(Int32*, UChar*, Int32, Int32, Int32);
extern void BZ2_hbMakeCodeLengths(UChar*, Int32*, Int32, Int32);
/*-- states for decompression. --*/
#define BZ_X_IDLE 1
#define BZ_X_OUTPUT 2
#define BZ_X_MAGIC_1 10
#define BZ_X_MAGIC_2 11
#define BZ_X_MAGIC_3 12
#define BZ_X_MAGIC_4 13
#define BZ_X_BLKHDR_1 14
#define BZ_X_BLKHDR_2 15
#define BZ_X_BLKHDR_3 16
#define BZ_X_BLKHDR_4 17
#define BZ_X_BLKHDR_5 18
#define BZ_X_BLKHDR_6 19
#define BZ_X_BCRC_1 20
#define BZ_X_BCRC_2 21
#define BZ_X_BCRC_3 22
#define BZ_X_BCRC_4 23
#define BZ_X_RANDBIT 24
#define BZ_X_ORIGPTR_1 25
#define BZ_X_ORIGPTR_2 26
#define BZ_X_ORIGPTR_3 27
#define BZ_X_MAPPING_1 28
#define BZ_X_MAPPING_2 29
#define BZ_X_SELECTOR_1 30
#define BZ_X_SELECTOR_2 31
#define BZ_X_SELECTOR_3 32
#define BZ_X_CODING_1 33
#define BZ_X_CODING_2 34
#define BZ_X_CODING_3 35
#define BZ_X_MTF_1 36
#define BZ_X_MTF_2 37
#define BZ_X_MTF_3 38
#define BZ_X_MTF_4 39
#define BZ_X_MTF_5 40
#define BZ_X_MTF_6 41
#define BZ_X_ENDHDR_2 42
#define BZ_X_ENDHDR_3 43
#define BZ_X_ENDHDR_4 44
#define BZ_X_ENDHDR_5 45
#define BZ_X_ENDHDR_6 46
#define BZ_X_CCRC_1 47
#define BZ_X_CCRC_2 48
#define BZ_X_CCRC_3 49
#define BZ_X_CCRC_4 50
/*-- Constants for the fast MTF decoder. --*/
#define MTFA_SIZE 4096
#define MTFL_SIZE 16
/*-- Structure holding all the decompression-side stuff. --*/
typedef struct {
/* pointer back to the struct bz_stream */
bz_stream* strm;
/* state indicator for this stream */
Int32 state;
/* for doing the final run-length decoding */
UChar state_out_ch;
Int32 state_out_len;
Bool blockRandomised;
BZ_RAND_DECLS;
/* the buffer for bit stream reading */
UInt32 bsBuff;
Int32 bsLive;
/* misc administratium */
Int32 blockSize100k;
Bool smallDecompress;
Int32 currBlockNo;
Int32 verbosity;
/* for undoing the Burrows-Wheeler transform */
Int32 origPtr;
UInt32 tPos;
Int32 k0;
Int32 unzftab[256];
Int32 nblock_used;
Int32 cftab[257];
Int32 cftabCopy[257];
/* for undoing the Burrows-Wheeler transform (FAST) */
UInt32* tt;
/* for undoing the Burrows-Wheeler transform (SMALL) */
UInt16* ll16;
UChar* ll4;
/* stored and calculated CRCs */
UInt32 storedBlockCRC;
UInt32 storedCombinedCRC;
UInt32 calculatedBlockCRC;
UInt32 calculatedCombinedCRC;
/* map of bytes used in block */
Int32 nInUse;
Bool inUse[256];
Bool inUse16[16];
UChar seqToUnseq[256];
/* for decoding the MTF values */
UChar mtfa[MTFA_SIZE];
Int32 mtfbase[256 / MTFL_SIZE];
UChar selector[BZ_MAX_SELECTORS];
UChar selectorMtf[BZ_MAX_SELECTORS];
UChar len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 limit[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 base[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 perm[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 minLens[BZ_N_GROUPS];
/* save area for scalars in the main decompress code */
Int32 save_i;
Int32 save_j;
Int32 save_t;
Int32 save_alphaSize;
Int32 save_nGroups;
Int32 save_nSelectors;
Int32 save_EOB;
Int32 save_groupNo;
Int32 save_groupPos;
Int32 save_nextSym;
Int32 save_nblockMAX;
Int32 save_nblock;
Int32 save_es;
Int32 save_N;
Int32 save_curr;
Int32 save_zt;
Int32 save_zn;
Int32 save_zvec;
Int32 save_zj;
Int32 save_gSel;
Int32 save_gMinlen;
Int32* save_gLimit;
Int32* save_gBase;
Int32* save_gPerm;
} DState;
/*-- Macros for decompression. --*/
#define BZ_GET_FAST(cccc) \
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) \
return True; \
s->tPos = s->tt[s->tPos]; \
cccc = (UChar)(s->tPos & 0xff); \
s->tPos >>= 8;
#define BZ_GET_FAST_C(cccc) \
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
if (c_tPos >= (UInt32)100000 * (UInt32)ro_blockSize100k) \
return True; \
c_tPos = c_tt[c_tPos]; \
cccc = (UChar)(c_tPos & 0xff); \
c_tPos >>= 8;
#define SET_LL4(i, n) \
{ \
if (((i)&0x1) == 0) \
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (n); \
else \
s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((n) << 4); \
}
#define GET_LL4(i) ((((UInt32)(s->ll4[(i) >> 1])) >> (((i) << 2) & 0x4)) & 0xF)
#define SET_LL(i, n) \
{ \
s->ll16[i] = (UInt16)(n & 0x0000ffff); \
SET_LL4(i, n >> 16); \
}
#define GET_LL(i) (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16))
#define BZ_GET_SMALL(cccc) \
/* c_tPos is unsigned, hence test < 0 is pointless. */ \
if (s->tPos >= (UInt32)100000 * (UInt32)s->blockSize100k) \
return True; \
cccc = BZ2_indexIntoF(s->tPos, s->cftab); \
s->tPos = GET_LL(s->tPos);
/*-- externs for decompression. --*/
extern Int32 BZ2_indexIntoF(Int32, Int32*);
extern Int32 BZ2_decompress(DState*);
extern void BZ2_hbCreateDecodeTables(Int32*, Int32*, Int32*, UChar*, Int32, Int32, Int32);
#endif
/*-- BZ_NO_STDIO seems to make nullptr disappear on some platforms. --*/
#ifdef BZ_NO_STDIO
#ifndef nullptr
#define nullptr 0
#endif
#endif
/*-------------------------------------------------------------*/
/*--- end bzlib_private.h ---*/
/*-------------------------------------------------------------*/
+854
View File
@@ -0,0 +1,854 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Compression machinery (not incl block sorting) ---*/
/*--- compress.cpp ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
/* CHANGES
0.9.0 -- original version.
0.9.0a/b -- no changes in this file.
0.9.0c -- changed setting of nGroups in sendMTFValues()
so as to do a bit better on small files
*/
#include "bzlib_private.hpp"
/*---------------------------------------------------*/
/*--- Bit stream I/O ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
void BZ2_bsInitWrite(EState* s) {
s->bsLive = 0;
s->bsBuff = 0;
}
/*---------------------------------------------------*/
static void bsFinishWrite(EState* s) {
while (s->bsLive > 0) {
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
s->numZ++;
s->bsBuff <<= 8;
s->bsLive -= 8;
}
}
/*---------------------------------------------------*/
#define bsNEEDW(nz) \
{ \
while (s->bsLive >= 8) { \
s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24); \
s->numZ++; \
s->bsBuff <<= 8; \
s->bsLive -= 8; \
} \
}
/*---------------------------------------------------*/
static __inline__ void bsW(EState* s, Int32 n, UInt32 v) {
bsNEEDW(n);
s->bsBuff |= (v << (32 - s->bsLive - n));
s->bsLive += n;
}
/*---------------------------------------------------*/
static void bsPutUInt32(EState* s, UInt32 u) {
bsW(s, 8, (u >> 24) & 0xffL);
bsW(s, 8, (u >> 16) & 0xffL);
bsW(s, 8, (u >> 8) & 0xffL);
bsW(s, 8, u & 0xffL);
}
/*---------------------------------------------------*/
static void bsPutUChar(EState* s, UChar c) {
bsW(s, 8, (UInt32)c);
}
/*---------------------------------------------------*/
/*--- The back end proper ---*/
/*---------------------------------------------------*/
/*---------------------------------------------------*/
static void makeMaps_e(EState* s) {
Int32 i;
s->nInUse = 0;
for (i = 0; i < 256; i++)
if (s->inUse[i]) {
s->unseqToSeq[i] = s->nInUse;
s->nInUse++;
}
}
/*---------------------------------------------------*/
static void generateMTFValues(EState* s) {
UChar yy[256];
Int32 i, j;
Int32 zPend;
Int32 wr;
Int32 EOB;
/*
After sorting (eg, here),
s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
and
((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
holds the original block data.
The first thing to do is generate the MTF values,
and put them in
((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
Because there are strictly fewer or equal MTF values
than block values, ptr values in this area are overwritten
with MTF values only when they are no longer needed.
The final compressed bitstream is generated into the
area starting at
(UChar*) (&((UChar*)s->arr2)[s->nblock])
These storage aliases are set up in bzCompressInit(),
except for the last one, which is arranged in
compressBlock().
*/
UInt32* ptr = s->ptr;
UChar* block = s->block;
UInt16* mtfv = s->mtfv;
makeMaps_e(s);
EOB = s->nInUse + 1;
for (i = 0; i <= EOB; i++)
s->mtfFreq[i] = 0;
wr = 0;
zPend = 0;
for (i = 0; i < s->nInUse; i++)
yy[i] = (UChar)i;
for (i = 0; i < s->nblock; i++) {
UChar ll_i;
AssertD(wr <= i, "generateMTFValues(1)");
j = ptr[i] - 1;
if (j < 0)
j += s->nblock;
ll_i = s->unseqToSeq[block[j]];
AssertD(ll_i < s->nInUse, "generateMTFValues(2a)");
if (yy[0] == ll_i) {
zPend++;
}
else {
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB;
wr++;
s->mtfFreq[BZ_RUNB]++;
}
else {
mtfv[wr] = BZ_RUNA;
wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2)
break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
{
UChar rtmp;
UChar* ryy_j;
UChar rll_i;
rtmp = yy[1];
yy[1] = yy[0];
ryy_j = &(yy[1]);
rll_i = ll_i;
while (rll_i != rtmp) {
UChar rtmp2;
ryy_j++;
rtmp2 = rtmp;
rtmp = *ryy_j;
*ryy_j = rtmp2;
};
yy[0] = rtmp;
j = ryy_j - &(yy[0]);
mtfv[wr] = j + 1;
wr++;
s->mtfFreq[j + 1]++;
}
}
}
if (zPend > 0) {
zPend--;
while (True) {
if (zPend & 1) {
mtfv[wr] = BZ_RUNB;
wr++;
s->mtfFreq[BZ_RUNB]++;
}
else {
mtfv[wr] = BZ_RUNA;
wr++;
s->mtfFreq[BZ_RUNA]++;
}
if (zPend < 2)
break;
zPend = (zPend - 2) / 2;
};
zPend = 0;
}
mtfv[wr] = EOB;
wr++;
s->mtfFreq[EOB]++;
s->nMTF = wr;
}
/*---------------------------------------------------*/
#define BZ_LESSER_ICOST 0
#define BZ_GREATER_ICOST 15
static void sendMTFValues(EState* s) {
Int32 t, i, j, k, gs, ge, totc, bt, bc;
Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
Int32 nGroups, nBytes;
/*--
UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
is a global since the decoder also needs it.
Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
are also globals only used in this proc.
Made global to keep stack frame size small.
--*/
UInt16 cost[BZ_N_GROUPS];
Int32 fave[BZ_N_GROUPS];
UInt16* mtfv = s->mtfv;
if (s->verbosity >= 3)
VPrintf3(" %d in block, %d after MTF & 1-2 coding, "
"%d+2 syms in use\n",
s->nblock,
s->nMTF,
s->nInUse);
alphaSize = s->nInUse + 2;
for (i = 0; i < BZ_N_GROUPS; i++)
for (j = 0; j < alphaSize; j++)
s->len[i][j] = BZ_GREATER_ICOST;
/*--- Decide how many coding tables to use ---*/
AssertH(s->nMTF > 0, 3001);
if (s->nMTF < 200)
nGroups = 2;
else if (s->nMTF < 600)
nGroups = 3;
else if (s->nMTF < 1200)
nGroups = 4;
else if (s->nMTF < 2400)
nGroups = 5;
else
nGroups = 6;
/*--- Generate an initial set of coding tables ---*/
{
Int32 nPart, remF, tFreq, aFreq;
nPart = nGroups;
remF = s->nMTF;
gs = 0;
while (nPart > 0) {
tFreq = remF / nPart;
ge = gs - 1;
aFreq = 0;
while (aFreq < tFreq && ge < alphaSize - 1) {
ge++;
aFreq += s->mtfFreq[ge];
}
if (ge > gs && nPart != nGroups && nPart != 1 && ((nGroups - nPart) % 2 == 1)) {
aFreq -= s->mtfFreq[ge];
ge--;
}
if (s->verbosity >= 3)
VPrintf5(" initial group %d, [%d .. %d], "
"has %d syms (%4.1f%%)\n",
nPart,
gs,
ge,
aFreq,
(100.0 * (float)aFreq) / (float)(s->nMTF));
for (i = 0; i < alphaSize; i++)
if (i >= gs && i <= ge)
s->len[nPart - 1][i] = BZ_LESSER_ICOST;
else
s->len[nPart - 1][i] = BZ_GREATER_ICOST;
nPart--;
gs = ge + 1;
remF -= aFreq;
}
}
/*---
Iterate up to BZ_N_ITERS times to improve the tables.
---*/
for (k = 0; k < BZ_N_ITERS; k++) {
for (i = 0; i < nGroups; i++)
fave[i] = 0;
for (i = 0; i < nGroups; i++)
for (j = 0; j < alphaSize; j++)
s->rfreq[i][j] = 0;
/*---
Set up an auxiliary length table which is used to fast-track
the common case (nGroups == 6).
---*/
if (nGroups == 6) {
for (i = 0; i < alphaSize; i++) {
s->len_pack[i][0] = (s->len[1][i] << 16) | s->len[0][i];
s->len_pack[i][1] = (s->len[3][i] << 16) | s->len[2][i];
s->len_pack[i][2] = (s->len[5][i] << 16) | s->len[4][i];
}
}
nSelectors = 0;
totc = 0;
gs = 0;
while (True) {
/*--- Set group start & end marks. --*/
if (gs >= s->nMTF)
break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF)
ge = s->nMTF - 1;
/*--
Calculate the cost of this group as coded
by each of the coding tables.
--*/
for (i = 0; i < nGroups; i++)
cost[i] = 0;
if (nGroups == 6 && 50 == ge - gs + 1) {
/*--- fast track the common case ---*/
UInt32 cost01, cost23, cost45;
UInt16 icv;
cost01 = cost23 = cost45 = 0;
#define BZ_ITER(nn) \
icv = mtfv[gs + (nn)]; \
cost01 += s->len_pack[icv][0]; \
cost23 += s->len_pack[icv][1]; \
cost45 += s->len_pack[icv][2];
BZ_ITER(0);
BZ_ITER(1);
BZ_ITER(2);
BZ_ITER(3);
BZ_ITER(4);
BZ_ITER(5);
BZ_ITER(6);
BZ_ITER(7);
BZ_ITER(8);
BZ_ITER(9);
BZ_ITER(10);
BZ_ITER(11);
BZ_ITER(12);
BZ_ITER(13);
BZ_ITER(14);
BZ_ITER(15);
BZ_ITER(16);
BZ_ITER(17);
BZ_ITER(18);
BZ_ITER(19);
BZ_ITER(20);
BZ_ITER(21);
BZ_ITER(22);
BZ_ITER(23);
BZ_ITER(24);
BZ_ITER(25);
BZ_ITER(26);
BZ_ITER(27);
BZ_ITER(28);
BZ_ITER(29);
BZ_ITER(30);
BZ_ITER(31);
BZ_ITER(32);
BZ_ITER(33);
BZ_ITER(34);
BZ_ITER(35);
BZ_ITER(36);
BZ_ITER(37);
BZ_ITER(38);
BZ_ITER(39);
BZ_ITER(40);
BZ_ITER(41);
BZ_ITER(42);
BZ_ITER(43);
BZ_ITER(44);
BZ_ITER(45);
BZ_ITER(46);
BZ_ITER(47);
BZ_ITER(48);
BZ_ITER(49);
#undef BZ_ITER
cost[0] = cost01 & 0xffff;
cost[1] = cost01 >> 16;
cost[2] = cost23 & 0xffff;
cost[3] = cost23 >> 16;
cost[4] = cost45 & 0xffff;
cost[5] = cost45 >> 16;
}
else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++) {
UInt16 icv = mtfv[i];
for (j = 0; j < nGroups; j++)
cost[j] += s->len[j][icv];
}
}
/*--
Find the coding table which is best for this group,
and record its identity in the selector table.
--*/
bc = 999999999;
bt = -1;
for (i = 0; i < nGroups; i++)
if (cost[i] < bc) {
bc = cost[i];
bt = i;
};
totc += bc;
fave[bt]++;
s->selector[nSelectors] = bt;
nSelectors++;
/*--
Increment the symbol frequencies for the selected table.
--*/
if (nGroups == 6 && 50 == ge - gs + 1) {
/*--- fast track the common case ---*/
#define BZ_ITUR(nn) s->rfreq[bt][mtfv[gs + (nn)]]++
BZ_ITUR(0);
BZ_ITUR(1);
BZ_ITUR(2);
BZ_ITUR(3);
BZ_ITUR(4);
BZ_ITUR(5);
BZ_ITUR(6);
BZ_ITUR(7);
BZ_ITUR(8);
BZ_ITUR(9);
BZ_ITUR(10);
BZ_ITUR(11);
BZ_ITUR(12);
BZ_ITUR(13);
BZ_ITUR(14);
BZ_ITUR(15);
BZ_ITUR(16);
BZ_ITUR(17);
BZ_ITUR(18);
BZ_ITUR(19);
BZ_ITUR(20);
BZ_ITUR(21);
BZ_ITUR(22);
BZ_ITUR(23);
BZ_ITUR(24);
BZ_ITUR(25);
BZ_ITUR(26);
BZ_ITUR(27);
BZ_ITUR(28);
BZ_ITUR(29);
BZ_ITUR(30);
BZ_ITUR(31);
BZ_ITUR(32);
BZ_ITUR(33);
BZ_ITUR(34);
BZ_ITUR(35);
BZ_ITUR(36);
BZ_ITUR(37);
BZ_ITUR(38);
BZ_ITUR(39);
BZ_ITUR(40);
BZ_ITUR(41);
BZ_ITUR(42);
BZ_ITUR(43);
BZ_ITUR(44);
BZ_ITUR(45);
BZ_ITUR(46);
BZ_ITUR(47);
BZ_ITUR(48);
BZ_ITUR(49);
#undef BZ_ITUR
}
else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++)
s->rfreq[bt][mtfv[i]]++;
}
gs = ge + 1;
}
if (s->verbosity >= 3) {
VPrintf2(" pass %d: size is %d, grp uses are ", k + 1, totc / 8);
for (i = 0; i < nGroups; i++)
VPrintf1("%d ", fave[i]);
VPrintf0("\n");
}
/*--
Recompute the tables based on the accumulated frequencies.
--*/
/* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
comment in huffman.c for details. */
for (i = 0; i < nGroups; i++)
BZ2_hbMakeCodeLengths(&(s->len[i][0]), &(s->rfreq[i][0]), alphaSize, 17 /*20*/);
}
AssertH(nGroups < 8, 3002);
AssertH(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZ_G_SIZE)), 3003);
/*--- Compute MTF values for the selectors. ---*/
{
UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
for (i = 0; i < nGroups; i++)
pos[i] = i;
for (i = 0; i < nSelectors; i++) {
ll_i = s->selector[i];
j = 0;
tmp = pos[j];
while (ll_i != tmp) {
j++;
tmp2 = tmp;
tmp = pos[j];
pos[j] = tmp2;
};
pos[0] = tmp;
s->selectorMtf[i] = j;
}
};
/*--- Assign actual codes for the tables. --*/
for (j = 0; j < nGroups; j++) {
minLen = 32;
maxLen = 0;
for (i = 0; i < alphaSize; i++) {
if (s->len[j][i] > maxLen)
maxLen = s->len[j][i];
if (s->len[j][i] < minLen)
minLen = s->len[j][i];
}
AssertH(!(maxLen > 17 /*20*/), 3004);
AssertH(!(minLen < 1), 3005);
BZ2_hbAssignCodes(&(s->code[j][0]), &(s->len[j][0]), minLen, maxLen, alphaSize);
}
/*--- Transmit the mapping table. ---*/
{
Bool inUse16[16];
for (i = 0; i < 16; i++) {
inUse16[i] = False;
for (j = 0; j < 16; j++)
if (s->inUse[i * 16 + j])
inUse16[i] = True;
}
nBytes = s->numZ;
for (i = 0; i < 16; i++)
if (inUse16[i])
bsW(s, 1, 1);
else
bsW(s, 1, 0);
for (i = 0; i < 16; i++)
if (inUse16[i])
for (j = 0; j < 16; j++) {
if (s->inUse[i * 16 + j])
bsW(s, 1, 1);
else
bsW(s, 1, 0);
}
if (s->verbosity >= 3)
VPrintf1(" bytes: mapping %d, ", s->numZ - nBytes);
}
/*--- Now the selectors. ---*/
nBytes = s->numZ;
bsW(s, 3, nGroups);
bsW(s, 15, nSelectors);
for (i = 0; i < nSelectors; i++) {
for (j = 0; j < s->selectorMtf[i]; j++)
bsW(s, 1, 1);
bsW(s, 1, 0);
}
if (s->verbosity >= 3)
VPrintf1("selectors %d, ", s->numZ - nBytes);
/*--- Now the coding tables. ---*/
nBytes = s->numZ;
for (t = 0; t < nGroups; t++) {
Int32 curr = s->len[t][0];
bsW(s, 5, curr);
for (i = 0; i < alphaSize; i++) {
while (curr < s->len[t][i]) {
bsW(s, 2, 2);
curr++; /* 10 */
};
while (curr > s->len[t][i]) {
bsW(s, 2, 3);
curr--; /* 11 */
};
bsW(s, 1, 0);
}
}
if (s->verbosity >= 3)
VPrintf1("code lengths %d, ", s->numZ - nBytes);
/*--- And finally, the block data proper ---*/
nBytes = s->numZ;
selCtr = 0;
gs = 0;
while (True) {
if (gs >= s->nMTF)
break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF)
ge = s->nMTF - 1;
AssertH(s->selector[selCtr] < nGroups, 3006);
if (nGroups == 6 && 50 == ge - gs + 1) {
/*--- fast track the common case ---*/
UInt16 mtfv_i;
UChar* s_len_sel_selCtr = &(s->len[s->selector[selCtr]][0]);
Int32* s_code_sel_selCtr = &(s->code[s->selector[selCtr]][0]);
#define BZ_ITAH(nn) \
mtfv_i = mtfv[gs + (nn)]; \
bsW(s, s_len_sel_selCtr[mtfv_i], s_code_sel_selCtr[mtfv_i])
BZ_ITAH(0);
BZ_ITAH(1);
BZ_ITAH(2);
BZ_ITAH(3);
BZ_ITAH(4);
BZ_ITAH(5);
BZ_ITAH(6);
BZ_ITAH(7);
BZ_ITAH(8);
BZ_ITAH(9);
BZ_ITAH(10);
BZ_ITAH(11);
BZ_ITAH(12);
BZ_ITAH(13);
BZ_ITAH(14);
BZ_ITAH(15);
BZ_ITAH(16);
BZ_ITAH(17);
BZ_ITAH(18);
BZ_ITAH(19);
BZ_ITAH(20);
BZ_ITAH(21);
BZ_ITAH(22);
BZ_ITAH(23);
BZ_ITAH(24);
BZ_ITAH(25);
BZ_ITAH(26);
BZ_ITAH(27);
BZ_ITAH(28);
BZ_ITAH(29);
BZ_ITAH(30);
BZ_ITAH(31);
BZ_ITAH(32);
BZ_ITAH(33);
BZ_ITAH(34);
BZ_ITAH(35);
BZ_ITAH(36);
BZ_ITAH(37);
BZ_ITAH(38);
BZ_ITAH(39);
BZ_ITAH(40);
BZ_ITAH(41);
BZ_ITAH(42);
BZ_ITAH(43);
BZ_ITAH(44);
BZ_ITAH(45);
BZ_ITAH(46);
BZ_ITAH(47);
BZ_ITAH(48);
BZ_ITAH(49);
#undef BZ_ITAH
}
else {
/*--- slow version which correctly handles all situations ---*/
for (i = gs; i <= ge; i++) {
bsW(s, s->len[s->selector[selCtr]][mtfv[i]], s->code[s->selector[selCtr]][mtfv[i]]);
}
}
gs = ge + 1;
selCtr++;
}
AssertH(selCtr == nSelectors, 3007);
if (s->verbosity >= 3)
VPrintf1("codes %d\n", s->numZ - nBytes);
}
/*---------------------------------------------------*/
void BZ2_compressBlock(EState* s, Bool is_last_block) {
if (s->nblock > 0) {
BZ_FINALISE_CRC(s->blockCRC);
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
s->combinedCRC ^= s->blockCRC;
if (s->blockNo > 1)
s->numZ = 0;
if (s->verbosity >= 2)
VPrintf4(" block %d: crc = 0x%08x, "
"combined CRC = 0x%08x, size = %d\n",
s->blockNo,
s->blockCRC,
s->combinedCRC,
s->nblock);
BZ2_blockSort(s);
}
s->zbits = (UChar*)(&((UChar*)s->arr2)[s->nblock]);
/*-- If this is the first block, create the stream header. --*/
if (s->blockNo == 1) {
BZ2_bsInitWrite(s);
bsPutUChar(s, BZ_HDR_B);
bsPutUChar(s, BZ_HDR_Z);
bsPutUChar(s, BZ_HDR_h);
bsPutUChar(s, (UChar)(BZ_HDR_0 + s->blockSize100k));
}
if (s->nblock > 0) {
bsPutUChar(s, 0x31);
bsPutUChar(s, 0x41);
bsPutUChar(s, 0x59);
bsPutUChar(s, 0x26);
bsPutUChar(s, 0x53);
bsPutUChar(s, 0x59);
/*-- Now the block's CRC, so it is in a known place. --*/
bsPutUInt32(s, s->blockCRC);
/*--
Now a single bit indicating (non-)randomisation.
As of version 0.9.5, we use a better sorting algorithm
which makes randomisation unnecessary. So always set
the randomised bit to 'no'. Of course, the decoder
still needs to be able to handle randomised blocks
so as to maintain backwards compatibility with
older versions of bzip2.
--*/
bsW(s, 1, 0);
bsW(s, 24, s->origPtr);
generateMTFValues(s);
sendMTFValues(s);
}
/*-- If this is the last block, add the stream trailer. --*/
if (is_last_block) {
bsPutUChar(s, 0x17);
bsPutUChar(s, 0x72);
bsPutUChar(s, 0x45);
bsPutUChar(s, 0x38);
bsPutUChar(s, 0x50);
bsPutUChar(s, 0x90);
bsPutUInt32(s, s->combinedCRC);
if (s->verbosity >= 2)
VPrintf1(" final combined CRC = 0x%08x\n ", s->combinedCRC);
bsFinishWrite(s);
}
}
/*-------------------------------------------------------------*/
/*--- end compress.c ---*/
/*-------------------------------------------------------------*/
+123
View File
@@ -0,0 +1,123 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Table for doing CRCs ---*/
/*--- crctable.cpp ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
#include "bzlib_private.hpp"
/*--
I think this is an implementation of the AUTODIN-II,
Ethernet & FDDI 32-bit CRC standard. Vaguely derived
from code by Rob Warnock, in Section 51 of the
comp.compression FAQ.
--*/
UInt32 BZ2_crc32Table[256] = {
/*-- Ugly, innit? --*/
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, 0x130476dcL, 0x17c56b6bL, 0x1a864db2L,
0x1e475005L, 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, 0x350c9b64L, 0x31cd86d3L,
0x3c8ea00aL, 0x384fbdbdL, 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, 0x5f15adacL,
0x5bd4b01bL, 0x569796c2L, 0x52568b75L, 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL,
0x95609039L, 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, 0xbe2b5b58L, 0xbaea46efL,
0xb7a96036L, 0xb3687d81L, 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, 0xd4326d90L,
0xd0f37027L, 0xddb056feL, 0xd9714b49L, 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL,
0xec7dd02dL, 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, 0x278206abL, 0x23431b1cL,
0x2e003dc5L, 0x2ac12072L, 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, 0x018aeb13L,
0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L,
0x53dc6066L, 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, 0xaca5c697L, 0xa864db20L,
0xa527fdf9L, 0xa1e6e04eL, 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, 0x8aad2b2fL,
0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, 0xf3b06b3bL, 0xf771768cL, 0xfa325055L,
0xfef34de2L, 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, 0xd5b88683L, 0xd1799b34L,
0xdc3abdedL, 0xd8fba05aL, 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, 0x7a089632L,
0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L,
0x285e1d47L, 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, 0x0315d626L, 0x07d4cb91L,
0x0a97ed48L, 0x0e56f0ffL, 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, 0xf12f560eL,
0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L,
0xc960ebb3L, 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, 0xae3afba2L, 0xaafbe615L,
0xa7b8c0ccL, 0xa379dd7bL, 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, 0x8832161aL,
0x8cf30badL, 0x81b02d74L, 0x857130c3L, 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, 0x7b827d21L, 0x7f436096L, 0x7200464fL,
0x76c15bf8L, 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, 0x119b4be9L, 0x155a565eL,
0x18197087L, 0x1cd86d30L, 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, 0x3793a651L,
0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL,
0xdbee767cL, 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, 0xf0a5bd1dL, 0xf464a0aaL,
0xf9278673L, 0xfde69bc4L, 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, 0x9abc8bd5L,
0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
};
/*-------------------------------------------------------------*/
/*--- end crctable.c ---*/
/*-------------------------------------------------------------*/
+732
View File
@@ -0,0 +1,732 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Decompression machinery ---*/
/*--- decompress.cpp ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
#include "bzlib_private.hpp"
/*---------------------------------------------------*/
static void makeMaps_d(DState* s) {
Int32 i;
s->nInUse = 0;
for (i = 0; i < 256; i++)
if (s->inUse[i]) {
s->seqToUnseq[s->nInUse] = i;
s->nInUse++;
}
}
/*---------------------------------------------------*/
#define RETURN(rrr) \
{ \
retVal = rrr; \
goto save_state_and_return; \
};
#define GET_BITS(lll, vvv, nnn) \
case lll: \
s->state = lll; \
while (True) { \
if (s->bsLive >= nnn) { \
UInt32 v; \
v = (s->bsBuff >> (s->bsLive - nnn)) & ((1 << nnn) - 1); \
s->bsLive -= nnn; \
vvv = v; \
break; \
} \
if (s->strm->avail_in == 0) \
RETURN(BZ_OK); \
s->bsBuff = (s->bsBuff << 8) | ((UInt32)(*((UChar*)(s->strm->next_in)))); \
s->bsLive += 8; \
s->strm->next_in++; \
s->strm->avail_in--; \
s->strm->total_in_lo32++; \
if (s->strm->total_in_lo32 == 0) \
s->strm->total_in_hi32++; \
}
#define GET_UCHAR(lll, uuu) GET_BITS(lll, uuu, 8)
#define GET_BIT(lll, uuu) GET_BITS(lll, uuu, 1)
/*---------------------------------------------------*/
#define GET_MTF_VAL(label1, label2, lval) \
{ \
if (groupPos == 0) { \
groupNo++; \
if (groupNo >= nSelectors) \
RETURN(BZ_DATA_ERROR); \
groupPos = BZ_G_SIZE; \
gSel = s->selector[groupNo]; \
gMinlen = s->minLens[gSel]; \
gLimit = &(s->limit[gSel][0]); \
gPerm = &(s->perm[gSel][0]); \
gBase = &(s->base[gSel][0]); \
} \
groupPos--; \
zn = gMinlen; \
GET_BITS(label1, zvec, zn); \
while (1) { \
if (zn > 20 /* the longest code */) \
RETURN(BZ_DATA_ERROR); \
if (zvec <= gLimit[zn]) \
break; \
zn++; \
GET_BIT(label2, zj); \
zvec = (zvec << 1) | zj; \
}; \
if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) \
RETURN(BZ_DATA_ERROR); \
lval = gPerm[zvec - gBase[zn]]; \
}
/*---------------------------------------------------*/
Int32 BZ2_decompress(DState* s) {
UChar uc;
Int32 retVal;
Int32 minLen, maxLen;
bz_stream* strm = s->strm;
/* stuff that needs to be saved/restored */
Int32 i;
Int32 j;
Int32 t;
Int32 alphaSize;
Int32 nGroups;
Int32 nSelectors;
Int32 EOB;
Int32 groupNo;
Int32 groupPos;
Int32 nextSym;
Int32 nblockMAX;
Int32 nblock;
Int32 es;
Int32 N;
Int32 curr;
Int32 zt;
Int32 zn;
Int32 zvec;
Int32 zj;
Int32 gSel;
Int32 gMinlen;
Int32* gLimit;
Int32* gBase;
Int32* gPerm;
if (s->state == BZ_X_MAGIC_1) {
/*initialise the save area*/
s->save_i = 0;
s->save_j = 0;
s->save_t = 0;
s->save_alphaSize = 0;
s->save_nGroups = 0;
s->save_nSelectors = 0;
s->save_EOB = 0;
s->save_groupNo = 0;
s->save_groupPos = 0;
s->save_nextSym = 0;
s->save_nblockMAX = 0;
s->save_nblock = 0;
s->save_es = 0;
s->save_N = 0;
s->save_curr = 0;
s->save_zt = 0;
s->save_zn = 0;
s->save_zvec = 0;
s->save_zj = 0;
s->save_gSel = 0;
s->save_gMinlen = 0;
s->save_gLimit = nullptr;
s->save_gBase = nullptr;
s->save_gPerm = nullptr;
}
/*restore from the save area*/
i = s->save_i;
j = s->save_j;
t = s->save_t;
alphaSize = s->save_alphaSize;
nGroups = s->save_nGroups;
nSelectors = s->save_nSelectors;
EOB = s->save_EOB;
groupNo = s->save_groupNo;
groupPos = s->save_groupPos;
nextSym = s->save_nextSym;
nblockMAX = s->save_nblockMAX;
nblock = s->save_nblock;
es = s->save_es;
N = s->save_N;
curr = s->save_curr;
zt = s->save_zt;
zn = s->save_zn;
zvec = s->save_zvec;
zj = s->save_zj;
gSel = s->save_gSel;
gMinlen = s->save_gMinlen;
gLimit = s->save_gLimit;
gBase = s->save_gBase;
gPerm = s->save_gPerm;
retVal = BZ_OK;
switch (s->state) {
GET_UCHAR(BZ_X_MAGIC_1, uc);
if (uc != BZ_HDR_B)
RETURN(BZ_DATA_ERROR_MAGIC);
GET_UCHAR(BZ_X_MAGIC_2, uc);
if (uc != BZ_HDR_Z)
RETURN(BZ_DATA_ERROR_MAGIC);
GET_UCHAR(BZ_X_MAGIC_3, uc)
if (uc != BZ_HDR_h)
RETURN(BZ_DATA_ERROR_MAGIC);
GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
if (s->blockSize100k < (BZ_HDR_0 + 1) || s->blockSize100k > (BZ_HDR_0 + 9))
RETURN(BZ_DATA_ERROR_MAGIC);
s->blockSize100k -= BZ_HDR_0;
if (s->smallDecompress) {
s->ll16 = (UInt16*)BZALLOC(s->blockSize100k * 100000 * sizeof(UInt16));
s->ll4 = (UChar*)BZALLOC(((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar));
if (s->ll16 == nullptr || s->ll4 == nullptr)
RETURN(BZ_MEM_ERROR);
}
else {
s->tt = (UInt32*)BZALLOC(s->blockSize100k * 100000 * sizeof(Int32));
if (s->tt == nullptr)
RETURN(BZ_MEM_ERROR);
}
GET_UCHAR(BZ_X_BLKHDR_1, uc);
if (uc == 0x17)
goto endhdr_2;
if (uc != 0x31)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_2, uc);
if (uc != 0x41)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_3, uc);
if (uc != 0x59)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_4, uc);
if (uc != 0x26)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_5, uc);
if (uc != 0x53)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_BLKHDR_6, uc);
if (uc != 0x59)
RETURN(BZ_DATA_ERROR);
s->currBlockNo++;
if (s->verbosity >= 2)
VPrintf1("\n [%d: huff+mtf ", s->currBlockNo);
s->storedBlockCRC = 0;
GET_UCHAR(BZ_X_BCRC_1, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_BCRC_2, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_BCRC_3, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_BCRC_4, uc);
s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
s->origPtr = 0;
GET_UCHAR(BZ_X_ORIGPTR_1, uc);
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
GET_UCHAR(BZ_X_ORIGPTR_2, uc);
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
GET_UCHAR(BZ_X_ORIGPTR_3, uc);
s->origPtr = (s->origPtr << 8) | ((Int32)uc);
if (s->origPtr < 0)
RETURN(BZ_DATA_ERROR);
if (s->origPtr > 10 + 100000 * s->blockSize100k)
RETURN(BZ_DATA_ERROR);
/*--- Receive the mapping table ---*/
for (i = 0; i < 16; i++) {
GET_BIT(BZ_X_MAPPING_1, uc);
if (uc == 1)
s->inUse16[i] = True;
else
s->inUse16[i] = False;
}
for (i = 0; i < 256; i++)
s->inUse[i] = False;
for (i = 0; i < 16; i++)
if (s->inUse16[i])
for (j = 0; j < 16; j++) {
GET_BIT(BZ_X_MAPPING_2, uc);
if (uc == 1)
s->inUse[i * 16 + j] = True;
}
makeMaps_d(s);
if (s->nInUse == 0)
RETURN(BZ_DATA_ERROR);
alphaSize = s->nInUse + 2;
/*--- Now the selectors ---*/
GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
if (nGroups < 2 || nGroups > 6)
RETURN(BZ_DATA_ERROR);
GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
if (nSelectors < 1)
RETURN(BZ_DATA_ERROR);
for (i = 0; i < nSelectors; i++) {
j = 0;
while (True) {
GET_BIT(BZ_X_SELECTOR_3, uc);
if (uc == 0)
break;
j++;
if (j >= nGroups)
RETURN(BZ_DATA_ERROR);
}
s->selectorMtf[i] = j;
}
/*--- Undo the MTF values for the selectors. ---*/
{
UChar pos[BZ_N_GROUPS], tmp, v;
for (i = 0; i < nGroups; i++)
pos[i] = i;
for (i = 0; i < nSelectors; i++) {
v = s->selectorMtf[i];
tmp = pos[v];
while (v > 0) {
pos[v] = pos[v - 1];
v--;
}
pos[0] = tmp;
s->selector[i] = tmp;
}
}
/*--- Now the coding tables ---*/
for (j = 0; j < nGroups; j++) {
GET_BITS(BZ_X_CODING_1, curr, 5);
for (i = 0; i < alphaSize; i++) {
while (True) {
if (curr < 1 || curr > 20)
RETURN(BZ_DATA_ERROR);
GET_BIT(BZ_X_CODING_2, uc);
if (uc == 0)
break;
GET_BIT(BZ_X_CODING_3, uc);
if (uc == 0)
curr++;
else
curr--;
}
s->len[j][i] = curr;
}
}
/*--- Create the Huffman decoding tables ---*/
for (j = 0; j < nGroups; j++) {
minLen = 32;
maxLen = 0;
for (i = 0; i < alphaSize; i++) {
if (s->len[j][i] > maxLen)
maxLen = s->len[j][i];
if (s->len[j][i] < minLen)
minLen = s->len[j][i];
}
BZ2_hbCreateDecodeTables(&(s->limit[j][0]),
&(s->base[j][0]),
&(s->perm[j][0]),
&(s->len[j][0]),
minLen,
maxLen,
alphaSize);
s->minLens[j] = minLen;
}
/*--- Now the MTF values ---*/
EOB = s->nInUse + 1;
nblockMAX = 100000 * s->blockSize100k;
groupNo = -1;
groupPos = 0;
for (i = 0; i <= 255; i++)
s->unzftab[i] = 0;
/*-- MTF init --*/
{
Int32 l, j, k;
k = MTFA_SIZE - 1;
for (l = 256 / MTFL_SIZE - 1; l >= 0; l--) {
for (j = MTFL_SIZE - 1; j >= 0; j--) {
s->mtfa[k] = (UChar)(l * MTFL_SIZE + j);
k--;
}
s->mtfbase[l] = k + 1;
}
}
/*-- end MTF init --*/
nblock = 0;
GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
while (True) {
if (nextSym == EOB)
break;
if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
es = -1;
N = 1;
do {
/* Check that N doesn't get too big, so that es doesn't
go negative. The maximum value that can be
RUNA/RUNB encoded is equal to the block size (post
the initial RLE), viz, 900k, so bounding N at 2
million should guard against overflow without
rejecting any legitimate inputs. */
if (N >= 2 * 1024 * 1024)
RETURN(BZ_DATA_ERROR);
if (nextSym == BZ_RUNA)
es = es + (0 + 1) * N;
else if (nextSym == BZ_RUNB)
es = es + (1 + 1) * N;
N = N * 2;
GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
} while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
es++;
uc = s->seqToUnseq[s->mtfa[s->mtfbase[0]]];
s->unzftab[uc] += es;
if (s->smallDecompress)
while (es > 0) {
if (nblock >= nblockMAX)
RETURN(BZ_DATA_ERROR);
s->ll16[nblock] = (UInt16)uc;
nblock++;
es--;
}
else
while (es > 0) {
if (nblock >= nblockMAX)
RETURN(BZ_DATA_ERROR);
s->tt[nblock] = (UInt32)uc;
nblock++;
es--;
};
continue;
}
else {
if (nblock >= nblockMAX)
RETURN(BZ_DATA_ERROR);
/*-- uc = MTF ( nextSym-1 ) --*/
{
Int32 i, j, k, l, lno, off;
UInt32 nn;
nn = (UInt32)(nextSym - 1);
if (nn < MTFL_SIZE) {
/* avoid general-case expense */
l = s->mtfbase[0];
uc = s->mtfa[l + nn];
while (nn > 3) {
Int32 z = l + nn;
s->mtfa[(z)] = s->mtfa[(z)-1];
s->mtfa[(z)-1] = s->mtfa[(z)-2];
s->mtfa[(z)-2] = s->mtfa[(z)-3];
s->mtfa[(z)-3] = s->mtfa[(z)-4];
nn -= 4;
}
while (nn > 0) {
s->mtfa[(l + nn)] = s->mtfa[(l + nn) - 1];
nn--;
};
s->mtfa[l] = uc;
}
else {
/* general case */
lno = nn / MTFL_SIZE;
off = nn % MTFL_SIZE;
l = s->mtfbase[lno] + off;
uc = s->mtfa[l];
while (l > s->mtfbase[lno]) {
s->mtfa[l] = s->mtfa[l - 1];
l--;
};
s->mtfbase[lno]++;
while (lno > 0) {
s->mtfbase[lno]--;
s->mtfa[s->mtfbase[lno]] = s->mtfa[s->mtfbase[lno - 1] + MTFL_SIZE - 1];
lno--;
}
s->mtfbase[0]--;
s->mtfa[s->mtfbase[0]] = uc;
if (s->mtfbase[0] == 0) {
k = MTFA_SIZE - 1;
for (i = 256 / MTFL_SIZE - 1; i >= 0; i--) {
for (j = MTFL_SIZE - 1; j >= 0; j--) {
s->mtfa[k] = s->mtfa[s->mtfbase[i] + j];
k--;
}
s->mtfbase[i] = k + 1;
}
}
}
}
/*-- end uc = MTF ( nextSym-1 ) --*/
s->unzftab[s->seqToUnseq[uc]]++;
if (s->smallDecompress)
s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]);
else
s->tt[nblock] = (UInt32)(s->seqToUnseq[uc]);
nblock++;
GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
continue;
}
}
/* Now we know what nblock is, we can do a better sanity
check on s->origPtr.
*/
if (s->origPtr < 0 || s->origPtr >= nblock)
RETURN(BZ_DATA_ERROR);
/*-- Set up cftab to facilitate generation of T^(-1) --*/
/* Check: unzftab entries in range. */
for (i = 0; i <= 255; i++) {
if (s->unzftab[i] < 0 || s->unzftab[i] > nblock)
RETURN(BZ_DATA_ERROR);
}
/* Actually generate cftab. */
s->cftab[0] = 0;
for (i = 1; i <= 256; i++)
s->cftab[i] = s->unzftab[i - 1];
for (i = 1; i <= 256; i++)
s->cftab[i] += s->cftab[i - 1];
/* Check: cftab entries in range. */
for (i = 0; i <= 256; i++) {
if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
/* s->cftab[i] can legitimately be == nblock */
RETURN(BZ_DATA_ERROR);
}
}
/* Check: cftab entries non-descending. */
for (i = 1; i <= 256; i++) {
if (s->cftab[i - 1] > s->cftab[i]) {
RETURN(BZ_DATA_ERROR);
}
}
s->state_out_len = 0;
s->state_out_ch = 0;
BZ_INITIALISE_CRC(s->calculatedBlockCRC);
s->state = BZ_X_OUTPUT;
if (s->verbosity >= 2)
VPrintf0("rt+rld");
if (s->smallDecompress) {
/*-- Make a copy of cftab, used in generation of T --*/
for (i = 0; i <= 256; i++)
s->cftabCopy[i] = s->cftab[i];
/*-- compute the T vector --*/
for (i = 0; i < nblock; i++) {
uc = (UChar)(s->ll16[i]);
SET_LL(i, s->cftabCopy[uc]);
s->cftabCopy[uc]++;
}
/*-- Compute T^(-1) by pointer reversal on T --*/
i = s->origPtr;
j = GET_LL(i);
do {
Int32 tmp = GET_LL(j);
SET_LL(j, i);
i = j;
j = tmp;
} while (i != s->origPtr);
s->tPos = s->origPtr;
s->nblock_used = 0;
if (s->blockRandomised) {
BZ_RAND_INIT_MASK;
BZ_GET_SMALL(s->k0);
s->nblock_used++;
BZ_RAND_UPD_MASK;
s->k0 ^= BZ_RAND_MASK;
}
else {
BZ_GET_SMALL(s->k0);
s->nblock_used++;
}
}
else {
/*-- compute the T^(-1) vector --*/
for (i = 0; i < nblock; i++) {
uc = (UChar)(s->tt[i] & 0xff);
s->tt[s->cftab[uc]] |= (i << 8);
s->cftab[uc]++;
}
s->tPos = s->tt[s->origPtr] >> 8;
s->nblock_used = 0;
if (s->blockRandomised) {
BZ_RAND_INIT_MASK;
BZ_GET_FAST(s->k0);
s->nblock_used++;
BZ_RAND_UPD_MASK;
s->k0 ^= BZ_RAND_MASK;
}
else {
BZ_GET_FAST(s->k0);
s->nblock_used++;
}
}
RETURN(BZ_OK);
endhdr_2:
GET_UCHAR(BZ_X_ENDHDR_2, uc);
if (uc != 0x72)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_3, uc);
if (uc != 0x45)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_4, uc);
if (uc != 0x38)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_5, uc);
if (uc != 0x50)
RETURN(BZ_DATA_ERROR);
GET_UCHAR(BZ_X_ENDHDR_6, uc);
if (uc != 0x90)
RETURN(BZ_DATA_ERROR);
s->storedCombinedCRC = 0;
GET_UCHAR(BZ_X_CCRC_1, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_CCRC_2, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_CCRC_3, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
GET_UCHAR(BZ_X_CCRC_4, uc);
s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
s->state = BZ_X_IDLE;
RETURN(BZ_STREAM_END);
default: AssertH(False, 4001);
}
AssertH(False, 4002);
save_state_and_return:
s->save_i = i;
s->save_j = j;
s->save_t = t;
s->save_alphaSize = alphaSize;
s->save_nGroups = nGroups;
s->save_nSelectors = nSelectors;
s->save_EOB = EOB;
s->save_groupNo = groupNo;
s->save_groupPos = groupPos;
s->save_nextSym = nextSym;
s->save_nblockMAX = nblockMAX;
s->save_nblock = nblock;
s->save_es = es;
s->save_N = N;
s->save_curr = curr;
s->save_zt = zt;
s->save_zn = zn;
s->save_zvec = zvec;
s->save_zj = zj;
s->save_gSel = gSel;
s->save_gMinlen = gMinlen;
s->save_gLimit = gLimit;
s->save_gBase = gBase;
s->save_gPerm = gPerm;
return retVal;
}
/*-------------------------------------------------------------*/
/*--- end decompress.c ---*/
/*-------------------------------------------------------------*/
+366
View File
@@ -0,0 +1,366 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <iostream>
#include <fstream>
#include <string>
#include <memory>
#include <queue>
#include <thread>
#include "bzlib.hpp"
#include "common/utility/utility.hpp"
#include "oneapi/tbb/flow_graph.h"
#include "oneapi/tbb/tick_count.h"
#include "oneapi/tbb/concurrent_queue.h"
// TODO: change memory allocation/deallocation to be managed in constructor/destructor
struct Buffer {
std::size_t len;
char* b;
};
struct BufferMsg {
BufferMsg() {}
BufferMsg(Buffer& inputBuffer, Buffer& outputBuffer, std::size_t seqId, bool isLast = false)
: inputBuffer(inputBuffer),
outputBuffer(outputBuffer),
seqId(seqId),
isLast(isLast) {}
static BufferMsg createBufferMsg(std::size_t seqId, std::size_t chunkSize) {
Buffer inputBuffer;
inputBuffer.b = new char[chunkSize];
inputBuffer.len = chunkSize;
Buffer outputBuffer;
std::size_t compressedChunkSize = chunkSize * 1.01 + 600; // compression overhead
outputBuffer.b = new char[compressedChunkSize];
outputBuffer.len = compressedChunkSize;
return BufferMsg(inputBuffer, outputBuffer, seqId);
}
static void destroyBufferMsg(const BufferMsg& destroyMsg) {
delete[] destroyMsg.inputBuffer.b;
delete[] destroyMsg.outputBuffer.b;
}
void markLast(std::size_t lastId) {
isLast = true;
seqId = lastId;
}
std::size_t seqId;
Buffer inputBuffer;
Buffer outputBuffer;
bool isLast;
};
class BufferCompressor {
public:
BufferCompressor(int blockSizeIn100KB) : m_blockSize(blockSizeIn100KB) {}
BufferMsg operator()(BufferMsg buffer) const {
if (!buffer.isLast) {
unsigned int outSize = buffer.outputBuffer.len;
BZ2_bzBuffToBuffCompress(buffer.outputBuffer.b,
&outSize,
buffer.inputBuffer.b,
buffer.inputBuffer.len,
m_blockSize,
0,
30);
buffer.outputBuffer.len = outSize;
}
return buffer;
}
private:
int m_blockSize;
};
class IOOperations {
public:
IOOperations(std::ifstream& inputStream, std::ofstream& outputStream, std::size_t chunkSize)
: m_inputStream(inputStream),
m_outputStream(outputStream),
m_chunkSize(chunkSize),
m_chunksRead(0) {}
void readChunk(Buffer& buffer) {
m_inputStream.read(buffer.b, m_chunkSize);
buffer.len = static_cast<std::size_t>(m_inputStream.gcount());
m_chunksRead++;
}
void writeChunk(const Buffer& buffer) {
m_outputStream.write(buffer.b, buffer.len);
}
std::size_t chunksRead() const {
return m_chunksRead;
}
std::size_t chunkSize() const {
return m_chunkSize;
}
bool hasDataToRead() const {
return m_inputStream.is_open() && !m_inputStream.eof();
}
private:
std::ifstream& m_inputStream;
std::ofstream& m_outputStream;
std::size_t m_chunkSize;
std::size_t m_chunksRead;
};
//-----------------------------------------------------------------------------------------------------------------------
//---------------------------------------Compression example based on async_node-----------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
typedef oneapi::tbb::flow::async_node<oneapi::tbb::flow::continue_msg, BufferMsg>
async_file_reader_node;
typedef oneapi::tbb::flow::async_node<BufferMsg, oneapi::tbb::flow::continue_msg>
async_file_writer_node;
class AsyncNodeActivity {
public:
AsyncNodeActivity(IOOperations& io)
: m_io(io),
m_fileWriterThread(&AsyncNodeActivity::writingLoop, this) {}
~AsyncNodeActivity() {
m_fileReaderThread.join();
m_fileWriterThread.join();
}
void submitRead(async_file_reader_node::gateway_type& gateway) {
gateway.reserve_wait();
std::thread(&AsyncNodeActivity::readingLoop, this, std::ref(gateway))
.swap(m_fileReaderThread);
}
void submitWrite(const BufferMsg& bufferMsg) {
m_writeQueue.push(bufferMsg);
}
private:
void readingLoop(async_file_reader_node::gateway_type& gateway) {
while (m_io.hasDataToRead()) {
BufferMsg bufferMsg = BufferMsg::createBufferMsg(m_io.chunksRead(), m_io.chunkSize());
m_io.readChunk(bufferMsg.inputBuffer);
gateway.try_put(bufferMsg);
}
sendLastMessage(gateway);
gateway.release_wait();
}
void writingLoop() {
BufferMsg buffer;
m_writeQueue.pop(buffer);
while (!buffer.isLast) {
m_io.writeChunk(buffer.outputBuffer);
m_writeQueue.pop(buffer);
}
}
void sendLastMessage(async_file_reader_node::gateway_type& gateway) {
BufferMsg lastMsg;
lastMsg.markLast(m_io.chunksRead());
gateway.try_put(lastMsg);
}
IOOperations& m_io;
oneapi::tbb::concurrent_bounded_queue<BufferMsg> m_writeQueue;
std::thread m_fileReaderThread;
std::thread m_fileWriterThread;
};
void fgCompressionAsyncNode(IOOperations& io, int blockSizeIn100KB) {
oneapi::tbb::flow::graph g;
AsyncNodeActivity asyncNodeActivity(io);
async_file_reader_node file_reader(
g,
oneapi::tbb::flow::unlimited,
[&asyncNodeActivity](const oneapi::tbb::flow::continue_msg& msg,
async_file_reader_node::gateway_type& gateway) {
asyncNodeActivity.submitRead(gateway);
});
oneapi::tbb::flow::function_node<BufferMsg, BufferMsg> compressor(
g, oneapi::tbb::flow::unlimited, BufferCompressor(blockSizeIn100KB));
oneapi::tbb::flow::sequencer_node<BufferMsg> ordering(g,
[](const BufferMsg& bufferMsg) -> size_t {
return bufferMsg.seqId;
});
// The node is serial to preserve the right order of buffers set by the preceding sequencer_node
async_file_writer_node output_writer(
g,
oneapi::tbb::flow::serial,
[&asyncNodeActivity](const BufferMsg& bufferMsg,
async_file_writer_node::gateway_type& gateway) {
asyncNodeActivity.submitWrite(bufferMsg);
});
make_edge(file_reader, compressor);
make_edge(compressor, ordering);
make_edge(ordering, output_writer);
file_reader.try_put(oneapi::tbb::flow::continue_msg());
g.wait_for_all();
}
//-----------------------------------------------------------------------------------------------------------------------
//---------------------------------------------Simple compression example------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
void fgCompression(IOOperations& io, int blockSizeIn100KB) {
oneapi::tbb::flow::graph g;
oneapi::tbb::flow::input_node<BufferMsg> file_reader(
g, [&io](oneapi::tbb::flow_control& fc) -> BufferMsg {
if (io.hasDataToRead()) {
BufferMsg bufferMsg = BufferMsg::createBufferMsg(io.chunksRead(), io.chunkSize());
io.readChunk(bufferMsg.inputBuffer);
return bufferMsg;
}
fc.stop();
return BufferMsg{};
});
file_reader.activate();
oneapi::tbb::flow::function_node<BufferMsg, BufferMsg> compressor(
g, oneapi::tbb::flow::unlimited, BufferCompressor(blockSizeIn100KB));
oneapi::tbb::flow::sequencer_node<BufferMsg> ordering(g, [](const BufferMsg& buffer) -> size_t {
return buffer.seqId;
});
oneapi::tbb::flow::function_node<BufferMsg> output_writer(
g, oneapi::tbb::flow::serial, [&io](const BufferMsg& bufferMsg) {
io.writeChunk(bufferMsg.outputBuffer);
BufferMsg::destroyBufferMsg(bufferMsg);
});
make_edge(file_reader, compressor);
make_edge(compressor, ordering);
make_edge(ordering, output_writer);
g.wait_for_all();
}
//-----------------------------------------------------------------------------------------------------------------------
bool endsWith(const std::string& str, const std::string& suffix) {
return str.find(suffix, str.length() - suffix.length()) != std::string::npos;
}
//-----------------------------------------------------------------------------------------------------------------------
int main(int argc, char* argv[]) {
oneapi::tbb::tick_count mainStartTime = oneapi::tbb::tick_count::now();
const std::string archiveExtension = ".bz2";
bool verbose = false;
bool asyncType;
std::string inputFileName;
int blockSizeIn100KB = 1; // block size in 100KB chunks
std::size_t memoryLimitIn1MB = 1; // memory limit for compression in megabytes granularity
utility::parse_cli_arguments(
argc,
argv,
utility::cli_argument_pack()
//"-h" option for displaying help is present implicitly
.arg(blockSizeIn100KB, "-b", "\t block size in 100KB chunks, [1 .. 9]")
.arg(verbose, "-v", "verbose mode")
.arg(memoryLimitIn1MB,
"-l",
"used memory limit for compression algorithm in 1MB (minimum) granularity")
.arg(asyncType, "-async", "use graph async_node-based implementation")
.positional_arg(inputFileName, "filename", "input file name"));
if (inputFileName.empty()) {
throw std::invalid_argument(
"Input file name is not specified. Try 'fgbzip2 -h' for more information.");
}
if (blockSizeIn100KB < 1 || blockSizeIn100KB > 9) {
throw std::invalid_argument("Incorrect block size. Try 'fgbzip2 -h' for more information.");
}
if (memoryLimitIn1MB < 1) {
throw std::invalid_argument(
"Incorrect memory limit size. Try 'fgbzip2 -h' for more information.");
}
if (verbose)
std::cout << "Input file name: " << inputFileName << "\n";
if (endsWith(inputFileName, archiveExtension)) {
throw std::invalid_argument("Input file already have " + archiveExtension + " extension.");
}
std::ifstream inputStream(inputFileName.c_str(), std::ios::in | std::ios::binary);
if (!inputStream.is_open()) {
throw std::invalid_argument("Cannot open " + inputFileName + " file.");
}
std::string outputFileName(inputFileName + archiveExtension);
std::ofstream outputStream(outputFileName.c_str(),
std::ios::out | std::ios::binary | std::ios::trunc);
if (!outputStream.is_open()) {
throw std::invalid_argument("Cannot open " + outputFileName + " file.");
}
// General interface to work with I/O buffers operations
std::size_t chunkSize = blockSizeIn100KB * 100 * 1024;
IOOperations io(inputStream, outputStream, chunkSize);
if (asyncType) {
if (verbose)
std::cout
<< "Running flow graph based compression algorithm with async_node based asynchronous IO operations."
<< "\n";
fgCompressionAsyncNode(io, blockSizeIn100KB);
}
else {
if (verbose)
std::cout << "Running flow graph based compression algorithm."
<< "\n";
fgCompression(io, blockSizeIn100KB);
}
inputStream.close();
outputStream.close();
utility::report_elapsed_time((oneapi::tbb::tick_count::now() - mainStartTime).seconds());
return 0;
}
+260
View File
@@ -0,0 +1,260 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Huffman coding low-level stuff ---*/
/*--- huffman.cpp ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
#include "bzlib_private.hpp"
/*---------------------------------------------------*/
#define WEIGHTOF(zz0) ((zz0)&0xffffff00)
#define DEPTHOF(zz1) ((zz1)&0x000000ff)
#define MYMAX(zz2, zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
#define ADDWEIGHTS(zw1, zw2) \
(WEIGHTOF(zw1) + WEIGHTOF(zw2)) | (1 + MYMAX(DEPTHOF(zw1), DEPTHOF(zw2)))
#define UPHEAP(z) \
{ \
Int32 zz, tmp; \
zz = z; \
tmp = heap[zz]; \
while (weight[tmp] < weight[heap[zz >> 1]]) { \
heap[zz] = heap[zz >> 1]; \
zz >>= 1; \
} \
heap[zz] = tmp; \
}
#define DOWNHEAP(z) \
{ \
Int32 zz, yy, tmp; \
zz = z; \
tmp = heap[zz]; \
while (True) { \
yy = zz << 1; \
if (yy > nHeap) \
break; \
if (yy < nHeap && weight[heap[yy + 1]] < weight[heap[yy]]) \
yy++; \
if (weight[tmp] < weight[heap[yy]]) \
break; \
heap[zz] = heap[yy]; \
zz = yy; \
} \
heap[zz] = tmp; \
}
/*---------------------------------------------------*/
void BZ2_hbMakeCodeLengths(UChar *len, Int32 *freq, Int32 alphaSize, Int32 maxLen) {
/*--
Nodes and heap entries run from 1. Entry 0
for both the heap and nodes is a sentinel.
--*/
Int32 nNodes, nHeap, n1, n2, i, j, k;
Bool tooLong;
Int32 heap[BZ_MAX_ALPHA_SIZE + 2];
Int32 weight[BZ_MAX_ALPHA_SIZE * 2];
Int32 parent[BZ_MAX_ALPHA_SIZE * 2];
for (i = 0; i < alphaSize; i++)
weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
while (True) {
nNodes = alphaSize;
nHeap = 0;
heap[0] = 0;
weight[0] = 0;
parent[0] = -2;
for (i = 1; i <= alphaSize; i++) {
parent[i] = -1;
nHeap++;
heap[nHeap] = i;
UPHEAP(nHeap);
}
AssertH(nHeap < (BZ_MAX_ALPHA_SIZE + 2), 2001);
while (nHeap > 1) {
n1 = heap[1];
heap[1] = heap[nHeap];
nHeap--;
DOWNHEAP(1);
n2 = heap[1];
heap[1] = heap[nHeap];
nHeap--;
DOWNHEAP(1);
nNodes++;
parent[n1] = parent[n2] = nNodes;
weight[nNodes] = ADDWEIGHTS(weight[n1], weight[n2]);
parent[nNodes] = -1;
nHeap++;
heap[nHeap] = nNodes;
UPHEAP(nHeap);
}
AssertH(nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002);
tooLong = False;
for (i = 1; i <= alphaSize; i++) {
j = 0;
k = i;
while (parent[k] >= 0) {
k = parent[k];
j++;
}
len[i - 1] = j;
if (j > maxLen)
tooLong = True;
}
if (!tooLong)
break;
/* 17 Oct 04: keep-going condition for the following loop used
to be 'i < alphaSize', which missed the last element,
theoretically leading to the possibility of the compressor
looping. However, this count-scaling step is only needed if
one of the generated Huffman code words is longer than
maxLen, which up to and including version 1.0.2 was 20 bits,
which is extremely unlikely. In version 1.0.3 maxLen was
changed to 17 bits, which has minimal effect on compression
ratio, but does mean this scaling step is used from time to
time, enough to verify that it works.
This means that bzip2-1.0.3 and later will only produce
Huffman codes with a maximum length of 17 bits. However, in
order to preserve backwards compatibility with bitstreams
produced by versions pre-1.0.3, the decompressor must still
handle lengths of up to 20. */
for (i = 1; i <= alphaSize; i++) {
j = weight[i] >> 8;
j = 1 + (j / 2);
weight[i] = j << 8;
}
}
}
/*---------------------------------------------------*/
void BZ2_hbAssignCodes(Int32 *code, UChar *length, Int32 minLen, Int32 maxLen, Int32 alphaSize) {
Int32 j, vec, i;
vec = 0;
for (j = minLen; j <= maxLen; j++) {
for (i = 0; i < alphaSize; i++)
if (length[i] == j) {
code[i] = vec;
vec++;
};
vec <<= 1;
}
}
/*---------------------------------------------------*/
void BZ2_hbCreateDecodeTables(Int32 *limit,
Int32 *base,
Int32 *perm,
UChar *length,
Int32 minLen,
Int32 maxLen,
Int32 alphaSize) {
Int32 pp, i, j, vec;
pp = 0;
for (i = minLen; i <= maxLen; i++)
for (j = 0; j < alphaSize; j++)
if (length[j] == i) {
perm[pp] = j;
pp++;
};
for (i = 0; i < BZ_MAX_CODE_LEN; i++)
base[i] = 0;
for (i = 0; i < alphaSize; i++)
base[length[i] + 1]++;
for (i = 1; i < BZ_MAX_CODE_LEN; i++)
base[i] += base[i - 1];
for (i = 0; i < BZ_MAX_CODE_LEN; i++)
limit[i] = 0;
vec = 0;
for (i = minLen; i <= maxLen; i++) {
vec += (base[i + 1] - base[i]);
limit[i] = vec - 1;
vec <<= 1;
}
for (i = minLen + 1; i <= maxLen; i++)
base[i] = ((limit[i - 1] + 1) << 1) - base[i];
}
/*-------------------------------------------------------------*/
/*--- end huffman.c ---*/
/*-------------------------------------------------------------*/
+104
View File
@@ -0,0 +1,104 @@
/*
Copyright (c) 2005-2021 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*-------------------------------------------------------------*/
/*--- Table for randomising repetitive blocks ---*/
/*--- randtable.cpp ---*/
/*-------------------------------------------------------------*/
/* ------------------------------------------------------------------
The original source for this example:
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.6 of 6 September 2010
Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
This program, "bzip2", the associated library "libbzip2", and all
documentation, are copyright (C) 1996-2010 Julian R Seward. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
3. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
4. The name of the author may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
Julian Seward, jseward@bzip.org
bzip2/libbzip2 version 1.0.6 of 6 September 2010
------------------------------------------------------------------ */
#include "bzlib_private.hpp"
/*---------------------------------------------*/
Int32 BZ2_rNums[512] = {
619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 985, 724, 205, 454, 863, 491, 741, 242, 949,
214, 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 419, 436, 278, 496, 867, 210, 399, 680,
480, 51, 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 862, 687, 507, 283, 482, 129, 807,
591, 733, 623, 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 170, 607, 520, 932, 727, 476,
693, 425, 174, 647, 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 909, 545, 703, 919, 874,
474, 882, 500, 594, 612, 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 161, 604, 958, 533,
221, 400, 386, 867, 600, 782, 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 98, 553, 163,
354, 666, 933, 424, 341, 533, 870, 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 469, 68,
770, 919, 190, 373, 294, 822, 808, 206, 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 715,
67, 618, 276, 204, 918, 873, 777, 604, 560, 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 645, 863, 803, 350, 139, 93, 354, 99, 820,
908, 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 653, 282, 762, 623, 680, 81, 927, 626,
789, 125, 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 170, 774, 972, 275, 999, 639, 495,
78, 352, 126, 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 669, 112, 134, 694, 363, 992,
809, 743, 168, 974, 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 344, 805, 988, 739, 511,
655, 814, 334, 249, 515, 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 433, 837, 553, 268,
926, 240, 102, 654, 459, 51, 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 946, 670, 656,
610, 738, 392, 760, 799, 887, 653, 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 680, 879,
194, 572, 640, 724, 926, 56, 204, 700, 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 297,
59, 87, 824, 713, 663, 412, 693, 342, 606, 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 140, 206, 73, 263, 980, 736, 876, 478, 430,
305, 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 369, 970, 294, 750, 807, 827, 150, 790,
288, 923, 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 896, 831, 547, 261, 524, 462, 293,
465, 502, 56, 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 768, 550, 608, 933, 378, 286,
215, 979, 792, 961, 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 372, 567, 466, 434, 645,
210, 389, 550, 919, 135, 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 920, 176, 193, 713,
857, 265, 203, 50, 668, 108, 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 936, 638
};
/*-------------------------------------------------------------*/
/*--- end randtable.c ---*/
/*-------------------------------------------------------------*/

Some files were not shown because too many files have changed in this diff Show More