Commit 14d6030e by Michael Schmid

added missing files

parent 74cbc558
*.sh binary
# The following files are ignored by Git
*.TMP
*.o
*.exe
build*
*~
*#
# Eclipse CDT project files
.project
.cproject
.settings/
# Latex output files
*.aux
*.bbl
*.blg
*.log
*.out
*.pdf
*.toc
*.synctex.gz
# Copyright (c) 2014-2016, Siemens AG. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause
language: cpp
compiler:
- gcc
- clang
install:
- sudo apt-get install -qq cppcheck
- sudo add-apt-repository --yes ppa:kalakris/cmake
- sudo apt-get update -qq
- sudo apt-get install cmake
script:
- cppcheck -q --enable=all *_c*
- mkdir build && cd build
- cmake ..
- make
- chmod a+x binaries/run_tests.sh
- ./binaries/run_tests.sh
Embedded Multicore Building Blocks (EMB²)
=========================================
Version 0.4.0
-------------
### Features:
- Added consistency checking functionality to dataflow
- Added C++ wrapper for base_c logging functions
- Reworked dataflow_cpp interface for easier usage
### Changes and improvements:
- Improved network plugin with better error checking and task cancellation support
- Revised dataflow_cpp so that network token count can now be set at runtime
- Added automatic determination of token count to dataflow_cpp
- Added checks for NULL pointers in C interface functions
- Extended mtapi_info_t to conform to the standard
- Fixed CodeSonar warnings across the code base
- Changed spinlock implementation to yield every 1024 spins now
- Changed asserts on interface visible parameters to execeptions
- Enabled reuse of main thread, which is configurable via node attributes
### Bug fixes:
- Fixed problem causing low performance on the Jetson TK1 board
- Fixed bug in mtapi_c causing a task wait to hang
- Fixes issue with the AMD APP SDK in the OpenCL plugin
- Fixed problem with automatic initialization in tasks_cpp
- Fixed memory leaks in tests
### Build system:
- Removed dependency on an installed OpenCL SDK
- Moved all MTAPI plugins into folder mtapi_plugins_c
- Resolved MSVC warnings and build problem
### Documentation:
- Updated README to reflect new directory structure
- Updated Doxygen documentation of dataflow_cpp for the improved interface
- Updated tutorial and examples to show the usage of dataflow_cpp
Version 0.3.2
-------------
### Features:
- Added central spinlock implementation for C/C++ and removed existing (decentral) ones
### Changes and improvements:
- Reworked and optimized hazard pointer implementation
- Adjusted interfaces of value pool and object pool
- Replaced C style casts
### Bug fixes:
- Fixed ordering of destruction and deallocation in value pool
- Fixed potential use of uninitialized memory in WaitFreeArrayValuePool and LockFreeTreeValuePool
### Build system:
- Given user the ability to append compiler flags
- Let Cmake return an error on Doxygen warnings when WARNINGS_ARE_ERRORS is enabled
- Fixed cpplint warnings
### Documentation:
- Added mutex concept
- Corrected library ordering/names in README (section "Using the Library")
- Improved exception messages
- Fixed typos in condition_var_test.cc
Version 0.3.1
-------------
### Features:
- None
### Changes and improvements:
- Removed one function argument from algorithms::Invoke
- Added "explicit" specifier to base type constructor of Atomic<BaseType*>
- Added "const" qualifier to dereference operator and member access operator of AtomicPointer<>
- Changed AtomicBase<>::CompareAndSwap to atomically return expected value
- Replaced constant in dataflow_cpp_test_simple.cc with corresponding macro
- Added initialization of atomic variable in hazard_pointer_test.cc to avoid warning with GCC 5.1
- Changed initial value of allocated_object_from_different_thread
- Added tests for ID Pool and check for memory leaks
- Updated unit test for the UniqueLock::Swap
### Bug fixes:
- Fixed implementation of ID pool (provided fewer elements than specified by capacity)
- Fixed unsigned overflow bug in timed wait function of condition variables
- Fixed implementation of UniqueLock::Swap
### Build system:
- Improved CMake output for automatic initialization option
- Fixed cpplint and unsigned/signed warnings
### Documentation:
- Fixed documentation of UniqueLock class
- Updated README file
Version 0.3.0
-------------
### Features:
* MTAPI:
- Implemented action plugin API
- Implemented load balancing for distributed/heterogeneous systems
- Implemented OpenCL action plugin
- Implemented network action plugin
- Added support for distributed/heterogeneous systems
### Changes and improvements:
* Base:
- Moved tick types to internal namespace and added duration typedefs
* MTAPI:
- Added multi-instance task support and test
- Improved notification of worker threads
- Moved interface for homogeneous systems to tasks_cpp
* Algorithms:
- Restricted partitioners to random access iterators
- Added unit tests for partitioners on large ranges
- Refactored to use tasks_cpp
* Dataflow:
- Removed spinlocks
- Simplified registration of processes (only sources need to be added)
- Increased number of task queues in unit test
- Added assertion in unit test
- Improved exception handling
- Removed stray include
- Refactored to use tasks_cpp
### Bug fixes:
- Fixed unit test for dataflow_cpp
- Fixed wait-free SPSC queue
### Build system:
- Fixed compilation for newer CMake Versions (>= 3.1)
- Changed task test to avoid Jenkins timeout
- Changed CMakeLists to avoid error if policy is unknown
- Added mtapi_network_c and mtapi_opencl_c to root CMakeLists
- Added tasks_cpp to test scripts / batch file
- Fixed cpplint warnings
### Documentation:
- Extended tutorial and examples regarding support for distributed/heterogeneous systems including plugins and new task interface
- Added Doxygen documentation for mtapi_opencl_c and mtapi_network_c
- Added Doxygen documentation to mtapi_ext.h
- Updated README and removed limitation to homogeneous systems
- Added missing concurrency tags in mtapi_cpp
Version 0.2.3
-------------
### Features:
- None
### Changes and improvements:
- Changed use of partitioners in ForEach, Reduce, Scan, Count, and MergeSort
- Added guard definition to QuickSort and MergeSort requiring random access iterators as inputs
- Unified behavior of algorithms on empty input
- Cleaned up MergeSort and Scan
- Extended computation of number of cores to take into account affinities
- Changed MTAPI_CHECK_STATUS in examples to use exit() instead of abort()
- Added overload for std::exception::what() in embb::base::Exception
- Added missing include in execution_policy.cc
- Added tests for Thread::ID (base_cpp), ExecutionPolicy (mtapi_cpp), and error cases in mtapi_c
- Added tests on empty and negative input ranges in algorithms
### Bug fixes:
- Fixed freeing of temporary buffer in MergeSortAllocate
- Fixed minor bugs in mtapi_c
- Fixed paths in Doxyfile.in template
### Build system:
- Added option to CMake to toggle automatic initialization of MTAPI C++ interface
- Changed run_tests_cygwin script to work with /bin/sh
- Modified create_tarball.sh script for completely automatic tarball creation
- Removed cppcheck warnings
- Removed cpplint warnings
- Updated partest
### Documentation:
- Added paragraphs in tutorial and README regarding performance impact of automatic initialization of MTAPI C++ interface
- Removed automatic collapsing of trees in Doxygen documentation due to incompatibility with latest versions of Doxygen
- Modified reference manual to consistently use function object concept
- Added description of default node attributes in mtapi_c and fixed typo in mtapi_cpp documentation
- Modified paragraph on documentation in README and fixed typo
Version 0.2.2
-------------
### Features:
- None
### Changes and improvements:
- Added checks for memory leaks in tests
- Added block size support in MergeSort
- Renamed all platform specific defines to EMBB_PLATFORM_*
- Changed all checks for platform specific defines to checks for EMBB_* defines
- Replaced C++11 initializer lists in examples with C++03 compliant statements
- Extended unit tests for MPMC queue with checks for relative order
- Added check for result of pthread_attr_destroy
- Added assert in embb_tss_get
- Moved ExecutionPolicy from algorithms to mtapi_cpp, removed Affinity
### Bug fixes:
- Fixed 64bit problem in atomics
- Fixed bug in dataflow_cpp causing network to hang
- Fixed bug in conversion of core_set
- Fixed fetch-and-add implementation to support armv7-a
- Fixed missing freeing of mutex attributes in case of error
- Fixed bug where closure was allocated with Allocation::New but deleted with operator delete
- Fixed inconsistent naming of unit test cases
- Fixed memory allocation in hazard pointer implementation by replacing calls to new and delete with EMB²-specific functions
- Fixed memory leak in tests for containers
- Fixed affinity implementation for FreeBSD
### Build system:
- Removed cppcheck warnings
- Removed cpplint warnings
### Documentation:
- Improved documentation of default values and priorities
- Revised template argument names in base_cpp and containers_cpp
- Moved ExecutionPolicy to CPP_MTAPI and Identity to CPP_ALGORITHMS Doxygen group
- Fixed description of token limit in tutorial
- Added Clang support to README
- Mentioned the ability to cross compile in README
- Added link to release files in README
- Minor corrections in README
- Updated copyright notice
- Changed year in tutorial.tex to 2015
Version 0.2.1
-------------
### Features:
- Added embb_core_count_available() implementation for FreeBSD.
### Changes and improvements:
- None
### Bug fixes:
- Fixed implementation of atomic operations on ARM.
- Fixed bug in HelpScan routine of hazard pointer implementation.
- Replaced inclusion of non-standard header malloc.h with stdlib.h.
### Build system:
- Added initial support for Clang.
- Added initial support for Travis.
- Fixed "Policy CMP0026 is not set" warning of CMake >= 3.0.2.
- Made build independent of build-dir / source-dir location.
- Fixed remaining GCC, Clang, MSVC, and cpplint warnings.
- Replaced /bin/bash with /usr/bin/env bash in scripts.
- Added executable flag to shell scripts.
- Omitted Doxygen "Makefiles" from tarball.
- Included patchlevel in name of installation directory on Linux.
- Added LaTeX .bbl and .blg files to ignore list.
### Documentation:
- Updated README file, created CHANGELOG file, and added markdown support.
- Corrected license in COPYING file (BSD 2-clause).
- Changed default Doxygen level for API to two.
- Added check for Doxyfile.in (if not present, do not add Doxygen target).
- Added PDF image of building blocks and updated tutorial.tex.
- Fixed typos and wording.
Version 0.2.0
-------------
- Initial version of open source release
\ No newline at end of file
Embedded Multicore Building Blocks (EMB²)
=========================================
Overview
--------
This project is licensed under the BSD 2-clause license given below.
The MTAPI header file is copyrighted by the Multicore Association
(http://www.multicore-association.org/) and licensed under the BSD 3-clause
license (see file include\embb\mtapi\c\mtapi.h).
License
-------
Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Embedded Multicore Building Blocks (EMB²)
=========================================
Overview
--------
The Embedded Multicore Building Blocks (EMB²) are an easy to use yet powerful
and efficient C/C++ library for the development of parallel applications. EMB²
has been specifically designed for embedded systems and the typical
requirements that accompany them, such as real-time capability and constraints
on memory consumption. As a major advantage, low-level operations are hidden
in the library which relieves software developers from the burden of thread
management and synchronization. This not only improves productivity of
parallel software development, but also results in increased reliability and
performance of the applications.
EMB² is independent of the hardware architecture (x86, ARM, ...) and runs on
various platforms, from small devices to large systems containing numerous
processor cores. It builds on MTAPI, a standardized programming interface for
leveraging task parallelism in embedded systems containing symmetric or
asymmetric multicore processors. A core feature of MTAPI is low-overhead
scheduling of fine-grained tasks among the available cores during runtime.
Unlike existing libraries, EMB² supports task priorities and affinities, which
allows the creation of soft real-time systems. Additionally, the scheduling
strategy can be optimized for non-functional requirements such as minimal
latency and fairness.
Besides the task scheduler, EMB² provides basic parallel algorithms, concurrent
data structures, and skeletons for implementing stream processing applications
(see figure below). These building blocks are largely implemented in a
non-blocking fashion, thus preventing frequently encountered pitfalls like
lock contention, deadlocks, and priority inversion. As another advantage in
real-time systems, the algorithms and data structures give certain progress
guarantees. For example, wait-free data structures guarantee system-wide
progress which means that every operation completes within a finite number of
steps independently of any other concurrent operations on the same data
structure.
<img src="doc/images/embb.png" alt="Building blocks of EMB²" width="500"/>
Community and Contact
---------------------
Project home:
- https://github.com/siemens/embb
Git:
- https://github.com/siemens/embb.git (HTTP)
- git@github.com:siemens/embb.git (SSH)
Mailing lists:
- embb-announcements@googlegroups.com (announcements)
- embb-dev@googlegroups.com (development)
Subscription:
- https://groups.google.com/forum/#!forum/embb-announcements/join
- https://groups.google.com/forum/#!forum/embb-dev/join
Contact:
- embb.info@gmail.com or
- tobias.schuele@siemens.com
License
-------
See the file "COPYING.md" in the project's root directory.
Requirements
------------
This project is based on the standards C99 (for C code) and C++03 (for C++
code) to be usable on a wide range of target systems. It has been tested on
the following OS/compiler/architecture combinations:
- Linux (Ubuntu 12.04) / GCC 4.8.1 / x86, x86_64
- Linux (Ubuntu 12.04) / Clang 3.0.0 / x86_64
- Linux (Ubuntu 14.04) / GCC 4.8.2 / ARMv7
- Windows
* MSVC 12.0.21005.1 REL / x86, x86_64
* MSVC 11.0.50727.42 VSLRSTAGE / x86, x86_64
Other compilers and operating systems may be supported without any changes to
the source code. The project includes unit tests that can be used to find out
whether a system not officially supported is suitable to run EMB². If there is
a requirement to support a system on which the unit tests do not pass, please
contact us: embb-dev@googlegroups.com.
Directory Structure
-------------------
EMB² consists of various building blocks. For some of them, there exist C and
C++ versions, others are only implemented in C++. The directory names are
postfixed with either "_cpp" or "_c" for the C++ and C versions, respectively.
Currently, EMB² contains the following components:
- base: base_c, base_cpp
- mtapi: mtapi_c, mtapi_cpp and
mtapi_plugins_c (mtapi_network_c and mtapi_opencl_c)
- tasks: tasks_cpp
- algorithms: algorithms_cpp
- dataflow: dataflow_cpp
- containers: containers_cpp
Each component consists of an include, a src, and a test subfolder that contain
the header files, source files, and unit tests, respectively.
Component base_c contains abstractions for threading, synchronization, atomic
operations, and other functionalities. As the name indicates, the code is
implemented in C. Component base_cpp is mainly a C++ wrapper around the base_c
functions. Component mtapi_c is a task scheduler written in C and mtapi_cpp a
C++ wrapper for the scheduler (mtapi_network_c and mtapi_opencl_c are scheduler
plugins for distributed and OpenCL-based heterogeneous systems, respectively).
To simplify programming of homogeneous systems, tasks_cpp contains abstractions
to the MTAPI interfaces. Component algorithms_cpp provides high-level constructs
for typical parallelization tasks in C++, and dataflow_cpp generic skeletons for
the development of parallel stream-based applications. Finally, containers_cpp
provides data structures for storing objects in a thread-safe way.
Build and Installation
----------------------
Note: It is recommended to build from a release file and not from a repository
snapshot in order to get the documentation and the examples out-of-the box.
The release files can be found at https://github.com/siemens/embb/releases.
EMB² is built using CMake (version 2.8.9 or higher). CMake is a build file
generator which allows to abstract from the concrete build tools. To generate
and invoke the platform-specific build files, open a shell (on Windows, use
the Visual Studio developer shell to have the correct environment variables)
and change to the project's root directory. Create a subdirectory, where you
want to build the library, e.g., "build". Change to that subdirectory. It is
assumed that the project's root directory is now the parent directory.
### 1. Generation of native build files
Choose an appropriate build file generator for your system.
- For Linux, GCC/Clang, x86/x86_64/ARM: "Unix Makefiles"
- For Windows, MSVC of VS 2013, x86: "Visual Studio 12"
- For Windows, MSVC of VS 2013, x86_64: "Visual Studio 12 Win64"
- For Windows, MSVC of VS 2012, x86: "Visual Studio 11"
- For Windows, MSVC of VS 2012, x86_64: "Visual Studio 11 Win64"
A list of all available generators can be displayed by typing "cmake" without
any options. The build files can be generated using the following command:
cmake -G <generator> .. [OPTIONS]
Note that on Linux, the architecture (32/64 bit) cannot be selected by the
generator. However, the build mode (Release/Debug) can be specified using the
option -DCMAKE_BUILD_TYPE=[Release|Debug]. If no build mode is given on Linux,
the default (Release) is used. The Visual Studio generators create build files
for both modes (the selection is done at build time).
You may choose a custom compiler instead the default one by defining
CMAKE_CXX_COMPILER and/or CMAKE_C_COMPILER. For example, to use Clang on Linux
use:
cmake .. -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang
In the same way you may cross compile to another platform. For example, to cross
compile to ARM Linux using GCC, you need to specify the cross compiler itself and
the target architecture as an argument to the compiler:
cmake .. -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-gcc++
-DCMAKE_CXX_FLAGS=-march=armv7-a
-DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc
-DCMAKE_C_FLAGS=-march=armv7-a
EMB² can be built with and without C++ exception handling, which has to be
specified on build file generation. When exceptions are turned off, an error
message is emitted and the program aborts in case of an exception within EMB².
To disable exceptions, add the option -DUSE_EXCEPTIONS=OFF.
Similarly, automatic initialization of the task scheduler by the MTAPI C++
interface can be disabled with -DUSE_AUTOMATIC_INITIALIZATION=OFF. This way,
unexpected delays after startup can be avoided, e.g. for timing measurements.
The tutorial of EMB² comes with example source files in doc/examples/. These
can be built with the other source files using CMake option -DBUILD_EXAMPLES=ON
in the generation step. Note, however, that the examples use C++11 features and
require a corresponding compiler.
Now you can generate the build files as shown by the following examples.
For a Linux Debug build with exception handling, type
cmake -G "Unix Makefiles" .. -DCMAKE_BUILD_TYPE=Debug
For a default Linux build without automatic MTAPI C++ initialization, type
cmake .. -DUSE_AUTOMATIC_INITIALIZATION=OFF
For a Windows build (VS 2013, x86) without exception handling, type
cmake -G "Visual Studio 12" .. -DUSE_EXCEPTIONS=OFF
Note that "Visual Studio 12" refers to the version number of Visual Studio and
not to the year in which it was released (2013).
### 2. Compiling and linking
As the next step, you can compile the library using the generated build files.
On Linux, the build mode (Release|Debug) is already given in the build files,
whereas on Windows, it has to be specified now.
For a Linux build, type
cmake --build .
For a Windows Release build, type
cmake --build . --config Release
### 3. Running the tests
To check whether EMB² was compiled correctly, run the tests. The test
executables are contained in the subfolder "binaries".
On Linux, type
binaries/run_tests.sh
On Windows, type
binaries\run_tests.bat
If no error message occurs, EMB² is working fine.
### 4. Installation
The default installation path on Linux is
/usr/local/
and on Windows
C:\Program Files\embb-X.Y.Z\ or C:\Program Files (x86)\embb-X.Y.Z
depending on the target architecture.
If you want a different installation path, you can change it now by typing
cmake -DINSTALL_PREFIX=YourCustomPath ..
The option "-DINSTALL_PREFIX=YourCustomPath" can also be given in Step 1.
To install the files, use the command
cmake --build . --target install
which copies the contents of the "install" folder to the "bin", "lib", and
"include" folders in the installation path. For the default paths, the
installation has to be run with administrator / root privileges.
Using the Library
-----------------
To use EMB², the include files have to be made available during compilation of
your application and the libraries have to be added during linking.
### 1. Using C++
If you want to use the C++ functionalities of EMB², you have to link the
following libraries (names will be different on Windows and on Linux) in the
given order:
embb_dataflow_cpp, embb_algorithms_cpp, embb_containers_cpp,
embb_mtapi_cpp, embb_mtapi_c, embb_base_cpp, embb_base_c
The C++ header files can be included as follows:
#include<embb/mtapi/mtapi.h>
#include<embb/base/base.h>
#include<embb/containers/containers.h>
#include<embb/dataflow/dataflow.h>
### 2. Using C
The following libraries have to be linked in the given order:
embb_mtapi_c, embb_base_c
The C header files can be included as follows:
#include<embb/mtapi/c/mtapi.h> or #include<mtapi.h>
#include<embb/base/c/base.h>
Documentation
-------------
The release files of EMB² come with a tutorial, example programs, and a
reference manual (HTML) describing the APIs. All documentation is contained in
the "doc" folder. The root document of the HTML reference is
"doc/reference/index.html". Note that generated documentation files are not
under version control and hence not contained in the repository. As mentioned
above, it is therefore recommended to download one of the packaged release
files in order to have ready-to-use documentation.
Code Quality
------------
For the C++ parts of EMB², we respect most rules of the "Google C++ Style
Guide" which are checked using the cpplint tool. However, we ignore some
rules, as they are not applicable or yield false results for this project.
For example, we respect the include order of the Google Style Guide, but use
<> instead of "" for project includes, which confuses the cpplint tool.
Moreover, we do not tolerate compiler warnings and regularly check the source
code using Cppcheck, a static analysis tool for C++.
Known Bugs and Limitations
--------------------------
- For memory management reasons, the number of threads EMB² can deal with
is bounded by a predefined but modifiable constant (see functions
embb_thread_get_max_count() / embb_thread_set_max_count() and class
embb::base::Thread).
- While MTAPI fully supports heterogeneous systems, the algorithms and
dataflow components are currently limited to homogeneous systems.
Development and Contribution
----------------------------
The EMB² team welcomes all kinds of contributions, preferably as pull requests
or patches via the development mailing lists (see above). If possible, please
refer to a current snapshot of the development branch.
EMB² is supposed to be easily portable to platforms unsupported so far. Almost
all platform specific code is located in the base_c and base_cpp modules. All
existing platform specific code is fenced by EMBB_PLATFORM_* defines.
To distinguish between compilers, EMB² currently uses the following defines:
- EMBB_PLATFORM_COMPILER_GNUC
- EMBB_PLATFORM_COMPILER_MSVC
- EMBB_PLATFORM_COMPILER_UNKNOWN
Different architectures are distinguished using:
- EMBB_PLATFORM_ARCH_X86
- EMBB_PLATFORM_ARCH_X86_32
- EMBB_PLATFORM_ARCH_X86_64
- EMBB_PLATFORM_ARCH_ARM
- EMBB_PLATFORM_ARCH_UNKNOWN
Threading APIs are switched by:
- EMBB_PLATFORM_THREADING_WINTHREADS
- EMBB_PLATFORM_THREADING_POSIXTHREADS
Please use these defines for new platform specific code. If additional defines
are needed, they can be defined in the config.h or cmake_config.h.in files.
Important Notes
---------------
- The MTAPI C++ interface supports automatic initialization, which allows for
easy usage of the MTAPI C++, Algorithms, and Dataflow components. For
performance measurements, explicit initialization is strongly recommended
since the measurements will otherwise include the initialization time of
MTAPI.
Links
-----
- Multicore Association:
http://www.multicore-association.org
- MTAPI:
http://www.multicore-association.org/workgroup/mtapi.php
- CMake:
http://www.cmake.org/
- Google C++ Style Guide:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.html
- cpplint:
http://google-styleguide.googlecode.com/svn/trunk/cpplint/
- Cppcheck:
http://cppcheck.sourceforge.net/
cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=TC_Toolchain.cmake
\ No newline at end of file
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ==============================================================================
# Project related options
# ==============================================================================
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "Embedded Multicore Building Blocks V@EMBB_BASE_VERSION_MAJOR@.@EMBB_BASE_VERSION_MINOR@.@EMBB_BASE_VERSION_PATCH@"
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = YES
INLINE_INHERITED_MEMB = YES
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = "@CMAKE_SOURCE_DIR@"
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 3
ALIASES = "notthreadsafe=\par Concurrency\nNot thread-safe\n" \
"threadsafe=\par Concurrency\nThread-safe\n" \
"lockfree=\par Concurrency\nThread-safe and lock-free\n" \
"waitfree=\par Concurrency\nThread-safe and wait-free\n" \
"memory=\par Dynamic memory allocation\n" \
"pre=\par Precondition\n" \
"post=\par Postcondition\n" \
"note=\par Note\n" \
"concept{1}=@ingroup \1\n@par Implemented concepts:\n@ref \1"
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = YES
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
# ==============================================================================
# Build related options
# ==============================================================================
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = NO
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE = "@CMAKE_SOURCE_DIR@/doc/reference/DoxygenLayout.xml"
CITE_BIB_FILES =
# ==============================================================================
# Options related to warning and progress messages
# ==============================================================================
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
# ==============================================================================
# Options related to input files
# ==============================================================================
INPUT = "@CMAKE_SOURCE_DIR@/doc/reference/embb.dox" \
"@CMAKE_SOURCE_DIR@/containers_cpp/include" \
"@CMAKE_SOURCE_DIR@/dataflow_cpp/include" \
"@CMAKE_SOURCE_DIR@/algorithms_cpp/include" \
"@CMAKE_SOURCE_DIR@/tasks_cpp/include" \
"@CMAKE_SOURCE_DIR@/mtapi_cpp/include" \
"@CMAKE_SOURCE_DIR@/base_cpp/include" \
"@CMAKE_SOURCE_DIR@/mtapi_c/include" \
"@CMAKE_SOURCE_DIR@/base_c/include" \
"@CMAKE_SOURCE_DIR@/mtapi_plugins_c/mtapi_opencl_c/include" \
"@CMAKE_SOURCE_DIR@/mtapi_plugins_c/mtapi_network_c/include"
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h \
*.cc \
*.c \
*.dox
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */test/* \
*/internal/*
EXCLUDE_SYMBOLS = *test* \
*::internal::*
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH = "@CMAKE_SOURCE_DIR@/doc"
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
# ==============================================================================
# Options related to source browsing
# ==============================================================================
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
# ==============================================================================
# Options related to alphabetical class index
# ==============================================================================
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 3
IGNORE_PREFIX = cm
# ==============================================================================
# Options related to HTML output
# ==============================================================================
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET = "@CMAKE_SOURCE_DIR@/doc/reference/DoxygenHTMLStyle.css"
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
# ==============================================================================
# Options related to LaTeX output
# ==============================================================================
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
# ==============================================================================
# Options related to RTF output
# ==============================================================================
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# ==============================================================================
# Options related to man page output
# ==============================================================================
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
# ==============================================================================
# Options related to XML output
# ==============================================================================
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
# ==============================================================================
# Options related to DOCBOOK output
# ==============================================================================
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
# ==============================================================================
# Options for the AutoGen Definitions output
# ==============================================================================
GENERATE_AUTOGEN_DEF = NO
# ==============================================================================
# Options related to Perl module output
# ==============================================================================
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
# ==============================================================================
# Options related to preprocessor
# ==============================================================================
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = protected=private \
DOXYGEN
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
# ==============================================================================
# Options related to external references
# ==============================================================================
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = NO
PERL_PATH = /usr/bin/perl
# ==============================================================================
# Options related to dot tool
# ==============================================================================
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = NO
COLLABORATION_GRAPH = NO
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = NO
INCLUDED_BY_GRAPH = NO
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = NO
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH = @DOT_PATH@
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
div.image img[src="embb.png"]{
width:500px;
}
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.6 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="no" title="" intro=""/> <!-- Set visibility to no to hide related pages -->
<tab type="modules" visible="yes" title="API" intro=""/>
<tab type="namespaces" visible="no" title="C++ Namespaces">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="Type Reference">
<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="no" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<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>
/**
\mainpage Overview
The Embedded Multicore Building Blocks (EMB<sup>2</sup>) are an easy to
use yet powerful and efficient C/C++ library for the development of
parallel applications. EMB<sup>2</sup> has been specifically designed
for embedded systems and the typical requirements that accompany them,
such as real-time capability and constraints on memory consumption. As a
major advantage, low-level operations are hidden in the library which
relieves software developers from the burden of thread management and
synchronization. This not only improves productivity of parallel
software development, but also results in increased reliability and
performance of the applications.
EMB<sup>2</sup> is independent of the hardware architecture (x86, ARM,
...) and runs on various platforms, from small devices to large systems
containing numerous processor cores. It builds on MTAPI, a standardized
programming interface for leveraging task parallelism in embedded
systems containing symmetric or asymmetric multicore processors. A core
feature of MTAPI is low-overhead scheduling of fine-grained tasks among
the available cores during runtime. Unlike existing libraries,
EMB<sup>2</sup> supports task priorities and affinities, which allows
the creation of soft real-time systems. Additionally, the scheduling
strategy can be optimized for non-functional requirements such as minimal
latency and fairness.
Besides the task scheduler, EMB<sup>2</sup> provides basic parallel
algorithms, concurrent data structures, and skeletons for implementing
stream processing applications (see figure below). These building blocks
are largely implemented in a non-blocking fashion, thus preventing
frequently encountered pitfalls like lock contention, deadlocks, and
priority inversion. As another advantage in real-time systems, the
algorithms and data structures give certain progress guarantees. For
example, wait-free data structures guarantee system-wide progress which
means that every operation completes within a finite number of steps
independently of any other concurrent operations on the same
data structure.
\image html ./images/embb.png
*/
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="1;url=./doxygen_html_generated/index.html">
<script type="text/javascript">
window.location.href = "./doxygen_html_generated/index.html"
</script>
<title>Page Redirection</title>
</head>
<body>
If you are not redirected automatically, follow the <a href='./doxygen_html_generated/index.html'>link</a>
</body>
</html>
\chapter{Algorithms}
\label{cha:algorithms}
The \emph{Algorithms} building block of \embb provides high-level constructs for typical parallelization tasks. They are aligned to the functions provided by the C++ Standard Library, but contain additional functionality typical for embedded systems such as task priorities. Although the algorithms can be used in a black-box way, it is good to have a basic understanding of their implementation: The algorithms split computations to be performed in parallel into tasks which are executed by the MTAPI task scheduler (cf. Chapter~\ref{cha:mtapi}). For that purpose, the tasks are stored in queues and mapped to a fixed number of worker threads at runtime. Since MTAPI allocates the necessary data structures during initialization, the maximum number of tasks in flight is fixed. In case one of the algorithms exceeds this limit, an exception is thrown.
\emph{\textbf{Note:} The \emph{Algorithms} building block is implemented using the MTAPI C++ interface. By calling \lstinline|embb::mtapi::Node::Initialize| task and other limits can be customized. Explicit initialization also eliminates unexpected delays when measuring performance. See Section~\ref{sec:mtapi_cpp_interface} for details.}
In the following, we look at parallel function invocation (Section~\ref{sec:algorithms_invoke}), sorting (Section~\ref{sec:algorithms_sorting}), counting (Section~\ref{sec:algorithms_counting}), foreach loops (Section~\ref{sec:algorithms_foreach}), reductions (Section~\ref{sec:algorithms_reductions}), and prefix computations (Section~\ref{sec:algorithms_prefix}).
\section{Function Invocation}
\label{sec:algorithms_invoke}
%In the previous section, we have considered data parallelism, that is, parallel execution of the same operation on a range of elements. Next, we consider parallel execution of several work packages encapsulated in functions.
Let us start with the parallel execution of several work packages encapsulated in functions. Suppose that the following functions operate on different data sets, and thus are independent of each other:
%
\\\inputlisting{../examples/algorithms/invoke/packages-snippet.h}
%
The functions can be executed in parallel using the \lstinline|ParallelInvoke| construct provided by {\embb}:
%
\\\inputlisting{../examples/algorithms/invoke/invocation-snippet.h}
%
Note that \lstinline|ParallelInvoke| waits until all its arguments have finished execution.
Next, let us consider a more elaborate example. The following piece of code shows a serial quick sort algorithm which we want to parallelize (do not care about the details of the \lstinline|Partition| function for the moment):
%
\\\inputlisting{../examples/algorithms/invoke/quick_sort-snippet.h}
%
A straightforward approach to parallelize this algorithm is to execute the recursive calls to \lstinline|Quicksort| in parallel. With \lstinline|ParallelInvoke| and lambdas, it is as simple as that:
%
\\\inputlisting{../examples/algorithms/invoke/parallel_quick_sort-snippet.h}
%
The lambdas capture the \lstinline|first|, \lstinline|mid|, and \lstinline|last| pointers to the range to be sorted and forward them to the recursive calls of quick sort. These are executed in parallel, where \lstinline|Invoke| does not return before both have finished execution. The above implementation of parallel quick sort is of course not yet optimal. In particular, the creation of new tasks should be stopped when a certain lower bound on the size of the subranges has been reached. The subranges can then be sorted sequentially in order to reduce the overhead for task creation and management. Fortunately, {\embb} already provides solutions for parallel sorting, which will be covered in the following section.
\section{Sorting}
\label{sec:algorithms_sorting}
%As sorting is a prominent problem that can benefit from multicore processors, {\embb} provides ready-to-use algorithms for parallel sorting.
For systems with constraints on memory consumption, the quick sort algorithm provided by \embb is usually the best choice, since it works in-place which means that it does not require additional memory. Considering real-time systems, however, its worst-case runtime of $O(N^2)$, where $N$ is the number of elements to be sorted, can be a problem. For this reason, {\embb} also provides a parallel merge sort algorithm. Merge sort does not work in-place, but has a predictable runtime complexity of $\Theta(N \log N)$. Assume we want to sort a vector of integers:
%
\\\inputlisting{../examples/algorithms/sorting/range_define-snippet.h}
%
Using quick sort, we simply write:
%
\\\inputlisting{../examples/algorithms/sorting/quick_sort-snippet.h}
%
The default invocation of \lstinline|QuickSort| uses \lstinline|std::less| with the iterators' \lstinline|value_type| as comparison operation. As a result, the range is sorted in ascending order. It is possible to provide a custom comparison operation, for example \lstinline|std::greater|, by passing it as a function object to the algorithm. Sorting the elements in descending can be accomplished as follows:
%
\\\inputlisting{../examples/algorithms/sorting/quick_sort_custom_compare-snippet.h}
The merge sort algorithm comes in two versions. The first version automatically allocates dynamic memory for temporary values when the algorithm is called. Its name is \lstinline|MergeSortAllocate| and it has the same parameters as \lstinline|QuickSort|. To enable the use of merge sort in environments that forbid dynamic memory allocation after initialization, the second version can be called with a pre-allocated temporary range of values:
%
\\\inputlisting{../examples/algorithms/sorting/merge_sort_preallocated-snippet.h}
%
The temporary range can be allocated at any time, e.g., during the initialization phase of the system.
\section{Counting}
\label{sec:algorithms_counting}
%Related to the above described summation reductions are the so-called counting operations.
\embb also provides functions for counting the number of elements in a range. Consider a range of integers from 0 to 3:
%
\\\inputlisting{../examples/algorithms/counting/setup-snippet.h}
%
To determine how often a specific value appears within the range, we could simply iterate over it and compare each element with the specified one. The \lstinline|Count| function does this in parallel, where the first two arguments specify the range and the third one the element to be counted:
%have to go through each of them, perform a comparison, and count the elements that compare equal. As in the reduction, the problem here is that a global counter is involved. The counting with equal comparison can be realized using the \lstinline|Count| function as
%
\\\inputlisting{../examples/algorithms/counting/count-snippet.h}
%
For the range given above, we have \lstinline|count == 2|.
In case the comparison operation is not equality, we can employ the \lstinline|CountIf| function. Here, the third argument is a unary predicate which evaluates to \lstinline|true| for each element to be counted. The following example shows how to count the number of values greater than 0:
%
\\\inputlisting{../examples/algorithms/counting/count_if-snippet.h}
\section{Foreach Loops}
\label{sec:algorithms_foreach}
A frequently encountered task in parallel programming is to apply some operation on a range of values, as illustrated in the example of Section~\ref{sec:introduction_function_objects}. In principle, one could apply the operation to all elements in parallel provided that there are no data dependencies. However, this results in unnecessary overhead if the number of elements is greater than the number of available processor cores $p$. A better solution is to partition the range into $p$ blocks and to process the elements of a block sequentially. With the \lstinline|ForEach| construct provided by \embb, users do not have to care about the partitioning, since this is done automatically. Similar to the Standard Library's \lstinline|for_each| function, it is sufficient to pass the operation in form of a function object. The following piece of code shows how to implement the example of Section~\ref{sec:introduction_function_objects} using \embb:
%
\\\inputlisting{../examples/algorithms/for_each/doubling-snippet.h}
In the above code snippet, the results of the computation overwrite the input. If the input has to be left unchanged, the results must be written to a separate output range. Thus, the operation requires two ranges. {\embb} supports such scenarios by the \lstinline|ZipIterator|, which wraps two iterators into one. Consider the following revised example for doubling the elements of a vector:
%
\\\inputlisting{../examples/algorithms/for_each/setup_zip-snippet.h}
%
Using the \lstinline|Zip| function as convenient way to create a zip iterator, the doubling can be performed as follows:
%
\\\inputlisting{../examples/algorithms/for_each/doubling_zip-snippet.h}
%
The argument to the lambda function is a \lstinline|ZipPair| with the iterators' reference value as template parameters. The elements pointed to by the zip iterator can be accessed via \lstinline|First()| and \lstinline|Second()|, similar to \lstinline|std::pair|.
\section{Reductions}
\label{sec:algorithms_reductions}
As mentioned in the previous section, the \lstinline|ForEach| construct requires the loop iterations do be independent of each other. However, this is not always the case. Imagine we want to sum up the values of a range, e.g., a vector of integers:
%
\\\inputlisting{../examples/algorithms/reduce/range_init-snippet.h}
%
Sequentially, this can be done by a simple loop:
%
\\\inputlisting{../examples/algorithms/reduce/sequential-snippet.h}
%
One might be tempted to sum up the elements in parallel using a foreach loop. The problem is that parallel accesses to \lstinline|sum| must be synchronized to avoid race conditions, which in fact sequentializes the loop. A more efficient approach is to compute intermediate sums for each block of the range and to sum them up at the end. For such purposes, {\embb} provides the function \lstinline|Reduce|:
%
\\\inputlisting{../examples/algorithms/reduce/parallel-snippet.h}
%
The third argument to \lstinline|Reduce| is the neutral element of the reduction operation, i.e., the element that does not change the result. In case of addition (\lstinline|std::plus|), the neutral element is 0. If we wanted to compute the product of the vector elements, the neutral element would be 1.
Next, let us consider the parallel computation of a dot product. Given two input ranges, we want to multiply each pair of input elements and sum up the products. The second input range is given as follows:
%
\\\inputlisting{../examples/algorithms/reduce/second_range_init-snippet.h}
%
The reduction consists of two steps: First, the input ranges are transformed and then, the reduction is performed on the transformed range. For that purpose, the \lstinline|Reduce| function allows to specify a transformation function object. By default, this is the identity functor which does not modify the input range. To implement the dot product, we can use the \lstinline|Zip| function (see Section~\ref{sec:algorithms_foreach}) and a lambda function for computing the transformed range:
%
\\\inputlisting{../examples/algorithms/reduce/dot_product-snippet.h}
\section{Prefix Computations}
\label{sec:algorithms_prefix}
Prefix computations (or scans) can be viewed as a generalization of reductions. They transform an input range $x_i \in X$ into an output range $y_i \in Y$ with $i=1,...,n$ such that
\begin{eqnarray*}
y_0 &=& id \cdot x_0 \\
y_1 &=& y_0 \cdot x_1 \\
&\vdots& \\
y_i &=& y_{i-1} \cdot x_i \\
&\vdots& \\
y_n &=& y_{n-1} \cdot x_n
\end{eqnarray*}
where $id$ is the identity (neutral element) with respect to the operation $(\cdot): X \times X \rightarrow Y$. As an example, consider the following range:
%
\\\inputlisting{../examples/algorithms/scan/setup-snippet.h}
%
Computing the prefix sums of \lstinline|input_range| sequentially is easy:
%
\\\inputlisting{../examples/algorithms/scan/sequential_prefix_sum-snippet.h}
%
Note the dependency on loop iteration $i-1$ to compute the result in iteration $i$. A special two-pass algorithm is used in the {\embb} function \lstinline|Scan| to perform prefix computations in parallel. Using \lstinline|Scan| to compute the prefix sums, we get:
%
\\\inputlisting{../examples/algorithms/scan/prefix_sum-snippet.h}
%
As in the case of reductions, the neutral element has to be given explicitly. Also, a transformation function can be passed as additional argument to \lstinline|Scan|. The elements of the input range are then transformed before given to the prefix operation.
\ No newline at end of file
\chapter{Containers}
\label{cha:containers}
Containers are essential for storing objects in an organized way. Unfortunately, the containers provided by the C++ Standard Library are not thread-safe. Attempts to read and write elements concurrently may corrupt the stored data. While such undefined behavior can be avoided by synchronizing all accesses using a mutex, this essentially eliminates any parallelism.
The containers provided by \embb enable a high degree of parallelism by design. They are implemented in a lock-free or wait-free fashion, thus avoiding any blocking operations. This way, multiple threads or tasks may access a container concurrently without suffering from typical side effects like convoying. Wait-free algorithms even guarantee that an operation completes within a bounded number of steps. Consequently, threads are immune to starvation which is critical for real-time systems.
In embedded systems, memory is often preallocated in the initialization phase to minimize the effort for memory management during operation and to prevent unpredictable out-of-memory errors. \embb containers have a fixed capacity and allocate the required memory at construction time. Consequently, they can be used in safety-critical application, where dynamic memory allocation after initialization is forbidden.
\section{Object Pools}
\label{sec:containers_object_pools}
An object pool allocates a fixed number of objects at construction. Objects can then be allocated from the pool and returned for later reuse. When implementing lock-free or wait-free algorithms, the underlying memory allocation scheme also to be lock-free or wait-free, respectively. However, memory allocation functions such as \lstinline|new| and \lstinline|delete| usually do not give any progress guarantees. To solve this problem, \embb provides lock-free and wait-free object pools.
Listing~\ref{lst:object_pool_lst1} shows an example, where we create in Line~\ref{lst:object_pool_lst1:line_create} an object pool with five objects of type \lstinline|int|. If nothing else is specified, the object-pool uses a wait-free implementation. Then, we allocate five objects from the object pool and store the obtained pointers in a temporary array. The actual allocation takes place in Line~\ref{lst:object_pool_lst1:line_allocate}. After that, we deallocate them in the second loop be calling \lstinline|FreeObject| on each pointer (see Line~\ref{lst:object_pool_lst1:line_free}).
\lstinputlisting[caption={Object pool -- initialization, allocation and
deallocation},label={lst:object_pool_lst1}]{../examples/containers/object_pool-snippet.h}
For actually allocating and deallocating objects, the object pool's implementation relies on a value pool which keeps track of the objects in use. If the value pool is implemented in a lock-free manner, the object pool is lock-free as well (analogously for wait-free pools). Currently, \embb provides two value pools: \lstinline|WaitFreeArrayValuePool| and \lstinline|LockFreeTreeValuePool|. Normally (if nothing is specified), the wait-free pool is used. For having a lock-free object pool instead, one has to specify the corresponding value pool to use as additional template parameter. If we replace Line~\ref{lst:object_pool_lst1:line_create} of the previous example with the following lines, the object pool is not wait-free anymore but lock-free (the values are of type
\lstinline|int| and initialized to \lstinline|0|):
%
\lstinputlisting{../examples/containers/object_pool_2-snippet.h}
%
This will result in a speed-up for most applications, but progress guarantees are weaker.
\section{Stacks}
\label{sec:containers_stacks}
As the name indicates, the class template \lstinline|LockFreeStack| implements a lock-free stack which stores elements according to the LIFO (Last-In, First-Out) principle. Listing~\ref{lst:stack_lst1} shows a simple example. In Line~\ref{lst:stack_lst1:line_create}, we create a stack of integers with a capacity of 10 elements.\footnote{Due to the necessary over-provisioning of memory in thread-safe memory management, the stack might be able to hold more than 10 elements, but is guaranteed to be able to hold at least 10 elements.} The stack provides two methods, \lstinline|TryPush| and \lstinline|TryPop|, both returning a Boolean value indicating success of the operation: \lstinline|TryPop| returns \lstinline|false| if the stack is empty, and \lstinline|TryPush| returns false if the stack is full. \lstinline|TryPop| returns the element removed from the stack via reference.
\lstinputlisting[caption={Stack -- initialization, push and
pop},label={lst:stack_lst1}]{../examples/containers/stack-snippet.h}
In Line~\ref{lst:stack_lst1:fail_pop} of Listing~\ref{lst:stack_lst1}, we try to pop an element from the empty stack, which has to fail. In the for-loop in Line \ref{lst:stack_lst1:loop1}, we fill the stack with \lstinline|int| values 0 $\ldots$ 4. Afterwards, in the loop in Line~\ref{lst:stack_lst1:loop2}, we pop five values (Line~\ref{lst:stack_lst1:pop}) from the stack into variable \lstinline|j|. According to the LIFO semantics, the values are popped in reverse order, i.e., we get the sequence 4 $\ldots$ 0. This is checked by the assertion in Line~\ref{lst:stack_lst1:assert}.
\section{Queues}
\label{sec:containers_queues}
There are two FIFO (First-In, First-Out) queue implementations in \embb, \lstinline|LockFreeMPMCQueue| and \lstinline|WaitFreeSPSCQueue|. The former permits multiple producers and multiple consumers (MPMC), whereas the latter is restricted to a single producer and a single consumer (SPSC). The interfaces are the same for both queues.
Listing~\ref{lst:queue_lst1} shows an example for the \lstinline|LockFreeMPMCQueue|. In Line~\ref{lst:queue_lst1:line_create}, we create a queue with element type \lstinline|int| and a capacity of 10 elements.\footnote{As in case of stacks, the queue may actually hold more than 10 elements.} The Boolean return value of the methods \lstinline|TryEnqueue| and \lstinline|TryDequeue| indicates success (\lstinline|false| if the queue is full or empty, respectively).
\lstinputlisting[caption={Queue -- initialization, enqueue and dequeue},label={lst:queue_lst1}]{../examples/containers/queues-snippet.h}
In Line~\ref{lst:queue_lst1:fail_pop} of Listing~\ref{lst:queue_lst1}, we try to dequeue an element from the empty queue, which has to fail. In the for-loop in Line~\ref{lst:queue_lst1:loop1}, we fill the queue with \lstinline|int| values 0 $\ldots$ 4. Afterwards, in the loop in Line~\ref{lst:queue_lst1:loop2}, we dequeue five values (Line~\ref{lst:queue_lst1:pop}) from the queue into variable \lstinline|j|. According to the FIFO semantics, the values are dequeued in the same order as they were enqueued, i.e., we get the sequence 0 $\ldots$ 4. This is checked by the assertion in Line~\ref{lst:queue_lst1:assert}.
\chapter{Dataflow}
\label{cha:dataflow}
With the \emph{Dataflow} building block, \embb provides generic skeletons for the development of parallel stream-based applications. These skeletons are based on dataflow process networks (DPNs), a model of computation which is, due to its simplicity and flexibility, widely employed in different domains like digital signal processing and imaging. As a major advantage, DPNs are deterministic which significantly simplifies testing and debugging. This is particularly important in safety-critical systems, where high demands are put on correctness and reliability. Moreover, DPNs are inherently parallel and hence, lend themselves well for execution on a multicore processor. In fact, they can be viewed as a generalization of pipelining, a frequently encountered parallel pattern.
%\begin{itemize}\setlength{\itemsep}{0pt}
% \item generic programming in the style of STL
% \item efficienct implementation using templates
% \item flexibility through pluggable components
% \item lock-free algorithms and data structures
% \item type safety and const correctness
% \item support for lambda functions and streaming operators
% \item abstraction from underlying hardware
% \item non-linear pipelines with multiple sources/sinks
% \item automatic memory management and load balancing
% \item inplace and non-inplace operations
% \item serial (in-order) and parallel (out-of-order) stages
% \item dynamic control of data streams (conditional execution)
%\end{itemize}
\emph{\textbf{Note:} The \emph{Dataflow} building block is implemented using the MTAPI C++ interface. Since MTAPI does not allocate memory after initialization, the number of tasks and other resources are limited. By calling \lstinline|embb::mtapi::Node::Initialize| these limits can be customized. Explicit initialization also eliminates unexpected delays when measuring performance. See Section~\ref{sec:mtapi_cpp_interface} for details.}
\section{Linear Pipelines}
Before we go into detail, we demonstrate the basic concepts of this building block by means of a simple application which finds and replaces strings in a file. Let us start with the sequential implementation. The program shown in Listing~\ref{lst:replace_seq} reads a file line by line and replaces each occurrence of a given string with a new string. The main part consists of the \lstinline|while| loop which performs three steps:
\begin{enumerate}\setlength{\itemsep}{0pt}
\item read a line from \lstinline|file| and store it in the string \lstinline|str|
\item replace each occurrence of \lstinline|what| in \lstinline|str| with \lstinline|with|
\item write the resulting string to \lstinline|cout|
\end{enumerate}
\begin{lstlisting}[float,caption={Sequential program for replacing strings in a file},label={lst:replace_seq}]
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
// replace all ocurrences of 'what' in 'str' with 'with'
void repl(string& str, const string &what,
const string& with) {
string::size_type pos = 0;
while((pos = str.find(what, pos)) != string::npos) {
str.replace(pos, what.length(), with);
pos += with.length();
}
}
int main(int argc, char *argv[]) {
// check and read command line arguments
if(argc != 4) {
cerr << "Usage: replace <what> <with> <file>" << endl;
exit(EXIT_FAILURE);
}
const string what(argv[1]), with(argv[2]);
// open input file
ifstream file(argv[3]);
if(!file) {
cerr << "Cannot open file " << argv[3] << endl;
exit(EXIT_FAILURE);
}
// read input file line by line and replace strings
string str;
while(getline(file, str)) {
repl(str, what, with);
cout << str << endl;
}
// close file and exit
file.close();
exit(EXIT_SUCCESS);
}
\end{lstlisting}
To run this program on a multicore processor, we may execute the above steps in a pipelined fashion. In this way, a new line can be read from the hard disk while the previous one is still being processed. Likewise, processing a string and writing the result to standard output can be performed in parallel. Thus, the pipeline may consist of three stages as depicted in Figure~\ref{fig:replace_par}.
\begin{figure}[!htb]
\centering%
\begin{tikzpicture}[box/.style={rectangle, draw, minimum width=2cm, minimum height=0.75cm, anchor=base}, arrow/.style={thick, ->, >=stealth'}]
\node (READ) [box] at (0,0) {};
\node (REPLACE) [box] at (3,0) {};
\node (WRITE) [box] at (6,0) {};
\node (FILE) [draw, cylinder, shape border rotate=90, minimum width=1.5cm, minimum height=1cm, anchor=base] at (0,-1.85) {};
\node (IO) [draw, trapezium, trapezium left angle=70, trapezium right angle=110, minimum width=1cm, minimum height=1cm, anchor=base] at (6,-1.75) {};
\node [anchor=mid] at (0,0) {\textbf{read}};
\node [anchor=mid] at (3,0) {\textbf{process}};
\node [anchor=mid] at (6,0) {\textbf{write}};
\draw [arrow] (FILE.north) -- (READ.south);
\draw [arrow] (READ.east) -- (REPLACE.west);
\draw [arrow] (REPLACE.east) -- (WRITE.west);
\draw [arrow] (WRITE.south) -- (IO.north);
\end{tikzpicture}
\caption{Pipeline for replacing strings in a file}
\label{fig:replace_par}
\end{figure}
This pipeline can be easily implemented using the Dataflow building block. As the first step, we have to include the \lstinline|dataflow.h| header file:
%
\\\inputlisting{../examples/dataflow/dataflow_include-snippet.h}
%
Then, we have to construct a \emph{network}. A network consists of a set of processes that are connected by communication channels.
%\footnote{Pipelines belong to the most simple networks, where the processes are connected in string-like (linear) fashion.}
\embb provides a class \lstinline|Network| that handles data routing and scheduling of your processes:
%
\\\inputlisting{../examples/dataflow/dataflow_network-snippet.h}
%
We need to prepare the network for the desired maximum number of elements that can be in the network at a time. The number of elements is limited to avoid that the network is flooded with new elements before the previous elements have been processed. In a linear pipeline, for example, this may happen if the source is faster than the sink. In our example, at most four elements may be processed simultaneously: one in the source, one in the sink, and two in the middle stage (see below). Finding an optimal value depends on the application and usually requires some experimentation. In general, large values boost the throughput but also increase the latency. Conversely, small values reduce the latency but may lead to a drop of performance in terms of throughput:
%
\\\inputlisting{../examples/dataflow/dataflow_make-snippet.h}
%
As the next step, we have to construct the processes shown in Figure~\ref{fig:replace_par}. The easiest way to construct a process is to wrap the user-defined code in a lambda function and to pass it to the network. The network constructs an object for that process and executes the lambda function whenever new data is available. There are several methods for constructing processes depending on their type. The process \textbf{read} is a \emph{source} process, since it produces data (by reading it from the specified file) but does not consume any data. Source processes are constructed from a function object
%
\\\inputlisting{../examples/dataflow/dataflow_source_function-snippet.h}
%
like this:
%
\\\inputlisting{../examples/dataflow/dataflow_declare_source-snippet.h}
%
%There are a couple of things to mention here. Firstly,
Note the template argument \lstinline|string| to \lstinline|Source|. This tells \embb that the process has exactly one \emph{port} of type \lstinline|string| and that this port is used to transmit data to other processes. The user-defined code can access the ports via the parameters of the function. Thus, each parameter corresponds to exactly one port. In our example, the result of the process is stored in a variable \lstinline|str|, which is passed by reference.
%Secondly, note that sources have to return a Boolean value. If the returned value is \lstinline|true|, the network will continue to execute the corresponding process. Otherwise, it will stop execution of the process and terminate when all previously produced data is processed.
The replacement of the strings can be done by a \emph{parallel} process, which means that multiple invocations of the process may be executed simultaneously. In general, processes that neither have any side effects nor maintain a state can safely be executed in parallel. This helps to avoid bottlenecks that arise when some processes are faster than others. Suppose, for example, that \textbf{replace} requires up to 50 ms to execute, whereas \textbf{read} and \textbf{write} each requires 10 ms to execute. If only one invocation of \textbf{replace} could be executed at a time, the throughput would be at most 20 elements per second. Since \textbf{replace} is a parallel process, however, the network may start a new invocation every 10 ms. Hence, up to five invocations may be executed in parallel, yielding a throughput of 100 elements per second. To compensate for variations in the runtime of parallel stages, \embb may execute them \emph{out-of-order}. As a result, the order in which the elements of a stream enter and leave parallel stages is not necessarily preserved. In our example, the runtime of \textbf{replace} may vary significantly due to the fact that not all lines have the same length and that the number of replacements depends on the content. However, let us now return to our example. The \textbf{replace} process is constructed from the function
%
\\\inputlisting{../examples/dataflow/dataflow_replace_function-snippet.h}
%
like this:
%
\\\inputlisting{../examples/dataflow/dataflow_declare_replace-snippet.h}
%
The template parameter \lstinline|Network::Inputs<string>| specifies that the process has one port serving as input. Analogously, \lstinline|Network::Outputs<string>| specifies that there is one port serving as output.
Since the last process (\textbf{write}) does not have any outputs, we make it a \emph{Sink}. Unlike parallel processes, sinks are always executed \emph{in-order}. \embb takes care that the elements are automatically reordered according to their original order in the stream. In this way, the externally visible behavior is preserved even if some parallel stages may be executed out-of-order. The function
%
\\\inputlisting{../examples/dataflow/dataflow_sink_function-snippet.h}
%
is used to construct the sink:
%
\\\inputlisting{../examples/dataflow/dataflow_declare_sink-snippet.h}
%
%In order to avoid that the received string is overwritten accidentally, the parameter \lstinline|str| corresponding to the input port of \lstinline|write| must be constant.\\
\emph{\textbf{Note:} If you parallelize your own application using \embb and your compiler emits a lengthy error message containing lots of templates, it is very likely that for at least one process, the ports and their directions do not match the signature of the given function.}
As the last step, we have to connect the processes (ports). This is straightforward using the C++ stream operator:
%
\\\inputlisting{../examples/dataflow/dataflow_connect-snippet.h}
%
Then we can start the network:
%
\\\inputlisting{../examples/dataflow/dataflow_run-snippet.h}
%
Note that you will probably not observe a speedup when you run this program on a multicore processor. One reason for this is that input$/$output operations like reading a file from the hard disk and writing the output to the screen are typically a bottleneck. Moreover, the amount of work done in the middle stage of the pipeline (\textbf{replace}) is rather low. To outweigh the overhead for parallel execution, the amount of work must be much higher. In image processing, for example, a single pipeline stage may process a complete image. To sum up, we haven chosen this example for its simplicity, not for its efficiency.
% ----------------------------------------------------------------------
\section{Nonlinear Pipelines}
% ----------------------------------------------------------------------
Some applications exhibit a more complex structure than the linear pipeline presented in the previous section. Typical examples are applications where the result of a pipeline stage is used by more than one successor stage. Such pipelines are said to be nonlinear. In principle, every nonlinear pipeline can be transformed to a linear one as depicted in Figure~\ref{fig:linearization}. However, this increases the latency and complicates the implementation due to data that must be passed through intermediate stages. In Figure~\ref{fig:linearization}, for example, the data transferred from stage A to stage C must be passed through stage B in the linearized implementation.
\begin{figure}[!htb]
\centering%
\begin{tikzpicture}
\matrix[column sep=1cm, row sep=0cm] {
\dpnser{A}{A}; & & \dpnser{D}{D}; \\
& \dpnser{C}{C}; & \\
\dpnser{B}{B}; & & \dpnser{E}{E}; \\
};
\draw [edgestyle] (A.east) -- (C);
\draw [edgestyle] (B.east) -- (C);
\draw [edgestyle] (C) -- (D.west);
\draw [edgestyle] (C) -- (E.west);
\end{tikzpicture}
\hspace{1cm}
\begin{tikzpicture}
\matrix[column sep=1cm, row sep=0cm] {
\dpnser{A}{A}; & & \dpnser{D}{D}; \\
& \dpnser{C}{C}; & \\
\dpnser{B}{B}; & & \dpnser{E}{E}; \\
};
\draw [edgestyle] (A) -- (B);
\draw [edgestyle] (B.east) -- (C);
\draw [edgestyle] (C) -- (D.west);
\draw [edgestyle] (D) -- (E);
\end{tikzpicture}
\caption{Nonlinear pipeline and linearized variant}
\label{fig:linearization}
\end{figure}
Nonlinear pipelines can be implemented as they are using \embb, i.e., there is need not linearize them. As an example, let us consider the implementation of a sorting network. Sorting networks consist of a set of interconnected comparators and are used to sort sequences of data items. As depicted in Figure~\ref{fig:comparator}, each comparator sorts a pair of values by putting the smaller value to one output, and the larger one to the other output. Thus, a comparator can be viewed as a switch that transfers the values at the inputs to the outputs, either directly or by swapping them (cf.~Figure~\ref{fig:example_comparator}).
\begin{figure}[!htb]
\centering%
\begin{tikzpicture}[comparator/.style={rectangle, draw, minimum width=1cm, minimum height=2cm, anchor=south west}, arrow/.style={thick, ->, >=stealth'}]
\node [comparator] at (1,0) {};
\node [left] at (0.25,1.5) {$a$};
\node [left] at (0.25,0.5) {$b$};
\node [right] at (2.75,1.5) {$\min(a,b)$};
\node [right] at (2.75,0.5) {$\max(a,b)$};
\draw [arrow] (0.25,0.5) -- (1,0.5);
\draw [arrow] (0.25,1.5) -- (1,1.5);
\draw [arrow] (2,0.5) -- (2.75,0.5);
\draw [arrow] (2,1.5) -- (2.75,1.5);
\end{tikzpicture}
\caption{Block diagram of a comparator}
\label{fig:comparator}
\end{figure}
\begin{figure}[!htb]
\centering%
\begin{tikzpicture}[comparator/.style={rectangle, draw, minimum width=1cm, minimum height=2cm, anchor=south west}, line/.style={thick, dashed}, arrow/.style={thick, ->, >=stealth'}]
\node [comparator] at (1,0) {};
\node [left] at (0.25,1.5) {$1$};
\node [left] at (0.25,0.5) {$3$};
\node [right] at (2.75,1.5) {$1$};
\node [right] at (2.75,0.5) {$3$};
\draw [arrow] (0.25,0.5) -- (1,0.5);
\draw [arrow] (0.25,1.5) -- (1,1.5);
\draw [arrow] (2,0.5) -- (2.75,0.5);
\draw [arrow] (2,1.5) -- (2.75,1.5);
\draw [line] (1,1.5) -- (2,1.5);
\draw [line] (1,0.5) -- (2,0.5);
\end{tikzpicture}
\hspace{2cm}
\begin{tikzpicture}[comparator/.style={rectangle, draw, minimum width=1cm, minimum height=2cm, anchor=south west}, line/.style={thick, dashed}, arrow/.style={thick, ->, >=stealth'}]
\node [comparator] at (1,0) {};
\node [left] at (0.25,1.5) {$5$};
\node [left] at (0.25,0.5) {$2$};
\node [right] at (2.75,1.5) {$2$};
\node [right] at (2.75,0.5) {$5$};
\draw [arrow] (0.25,0.5) -- (1,0.5);
\draw [arrow] (0.25,1.5) -- (1,1.5);
\draw [arrow] (2,0.5) -- (2.75,0.5);
\draw [arrow] (2,1.5) -- (2.75,1.5);
\draw [line] (1,1.5) -- (2,0.5);
\draw [line] (1,0.5) -- (2,1.5);
\end{tikzpicture}
\caption{Example for the operating principle of a comparator}
\label{fig:example_comparator}
\end{figure}
Figure~\ref{fig:sorting_network} shows a sorting network with four inputs$/$outputs and five comparators. The numbers at the interconnections exemplify a ``run'' of the network. As can be seen from Figure~\ref{fig:sorting_network}, the comparators $C_1-C_4$ "sink" the largest value to the bottom and "float" the smallest value to the top. The final comparator $C_5$ simply sorts out the middle two values. In this way it is guaranteed that the values at the outputs occur in ascending order. %Note that the structure of the network makes it well-suited for sorting continuous streams of data in a pipelined fashion.
\begin{figure}[!htb]
\centering%
\begin{tikzpicture}[comparator/.style={rectangle, draw, minimum width=1cm, minimum height=2.5cm, anchor=south west}, line/.style={thick}, arrow/.style={thick, ->, >=stealth'}]
\node [comparator, minimum height=4cm] at (1,1.5) {$C_1$};
\node [comparator, minimum height=4cm] at (3,0) {$C_2$};
\node [comparator] at (5,3) {$C_3$};
\node [comparator] at (5,0) {$C_4$};
\node [comparator] at (7,1.5) {$C_5$};
\draw [arrow] (0,5) -- (1,5);
\draw [arrow] (2,5) -- (5,5);
\draw [arrow] (6,5) -- (9,5);
\draw [line] (0,3.5) -- (1,3.5);
\draw [arrow] (2,3.5) -- (3,3.5);
\draw [arrow] (4,3.5) -- (5,3.5);
\draw [arrow] (6,3.5) -- (7,3.5);
\draw [arrow] (8,3.5) -- (9,3.5);
\draw [arrow] (0,2) -- (1,2);
\draw [line] (2,2) -- (3,2);
\draw [arrow] (4,2) -- (5,2);
\draw [arrow] (6,2) -- (7,2);
\draw [arrow] (8,2) -- (9,2);
\draw [arrow] (0,0.5) -- (3,0.5);
\draw [arrow] (4,0.5) -- (5,0.5);
\draw [arrow] (6,0.5) -- (9,0.5);
\node [left] at (0,5.0) {$3$};
\node [left] at (0,3.5) {$2$};
\node [left] at (0,2.0) {$4$};
\node [left] at (0,0.5) {$1$};
\node [above] at (2.5,5.0) {$3$};
\node [above] at (4.5,3.5) {$1$};
\node [above] at (2.5,2.0) {$4$};
\node [above] at (4.5,0.5) {$2$};
\node [above] at (6.5,3.5) {$3$};
\node [above] at (6.5,2.0) {$2$};
\node [right] at (9,5.0) {$1$};
\node [right] at (9,3.5) {$2$};
\node [right] at (9,2.0) {$3$};
\node [right] at (9,0.5) {$4$};
\end{tikzpicture}
\caption{Sorting network with four inputs$/$outputs and five comparators}
\label{fig:sorting_network}
\end{figure}
Let us now consider the implementation of the sorting network using \embb. As in the previous example, we need three types of processes: one or more sources that produce a stream of data items, a total number of five processes that implement the comparators, and one or more sinks that consume the sorted sequences. The processes should be generic so that they can be used with different types. For example, in one application we might use the network to sort integers, and in another application to sort floating point values.
The following Listing shows the implementation of the source processes using classes instead of functions.\footnote{For the sake of brevity, we omit the functionality. A complete implementation can be found in the examples directory.}
%
\\\inputlisting{../examples/dataflow/dataflow_producer-snippet.h}
%
%In order to use an instance of a class as a process, it must be derived from one of the predfined base classes.
The class-based approach has several advantages besides the use of templates: Firstly, the creation of multiple processes is straightforward. Secondly, one can derive other processes from a given base class such as \lstinline|Producer|. Thirdly, it eases migration of existing code. For example, if you want to use an object of an existing class \lstinline|foo| as a process, you might derive a class \lstinline|bar| from \lstinline|foo|. The function operator of \lstinline|bar| then has access to the members provided by \lstinline|foo|.
%Thirdly, it eases migration of existing code by means of multiple inheritance. For example, if you want to use an object of an existing class \lstinline|foo| as a process, you might derive a class \lstinline|bar| from \lstinline|foo| and \lstinline|Network::Source<...>| (or any other process class). The function operator of \lstinline|bar| then has access to the members provided by \lstinline|foo|.
Each instance of the class \lstinline|Network| maintains a list of source processes that belong to the network.
% When you create a source process using \lstinline|MakeSource|, it is automatically added to this list. Otherwise, you must explicitly add it by a call to \lstinline|Add|. For example, if we want to feed our sorting network \lstinline|nw| with streams of integer values, we may write:
You must explicitly add all sources to the network by a call to \lstinline|AddSource|. For example, if we want to feed our sorting network \lstinline|nw| with four streams of integer values, we may write:
%
\\\inputlisting{../examples/dataflow/dataflow_declare_add_sources-snippet.h}
%
This is only necessary for source processes. All other processes are automatically found via a depth-first search starting from the source processes.
The code for the comparators looks like this:
%
\\\inputlisting{../examples/dataflow/dataflow_comparator-snippet.h}
%
Since the comparators neither have any side effects nor maintain a state, we allow multiple invocations to be executed in parallel.
% by deriving the class \lstinline|comparator| from the base class \lstinline|network<>::parallel|.
%In the above implementation of \lstinline|Comparator|, the inputs \lstinline|a| and \lstinline|b| are passed by value, which works fine if \lstinline|T| is a scalar type such as an integer or a float. However, since objects are passed by reference for efficiency reasons (unless otherwise specified), we cannot use classes as template argument for \lstinline|comparator|. To solve this problem, the classes \lstinline|in|, \lstinline|out|, and \lstinline|inout| define the parameter type that matches the given data type. As an example, \lstinline|in<int>::parameter_type| is simply \lstinline|int|, while \lstinline|in<foo>::parameter_type| yields \lstinline|const foo&| for a class \lstinline|foo|. A fully generic implementation of \lstinline|comparator| is shwon in Listing~\ref{lst:comparator_gen} (the objects of type \lstinline|T| must be comparable in order to compute the minimum and the maximum).
%
%\begin{lstlisting}[caption={Fully generic comparator process},label={lst:comparator_gen}]
%template <typename T>
%class Comparator {
%public:
% void Run(const T& a, const T& b, T& x, T& y) const {
% x = min(a,b);
% y = max(a,b);
% }
%};
%\end{lstlisting}
To check whether the resulting values are sorted, we use a single sink with four inputs:
%
\\\inputlisting{../examples/dataflow/dataflow_consumer-snippet.h}
%
In general, however, we could also have a sink for each output of the sorting network. There is no restriction on the number of sources and sinks a network may have.
\chapter{Introduction}
\section{Overview}
The Embedded Multicore Building Blocks (\embb) are an easy to use yet powerful and efficient C/C++ library for the development of parallel applications. \embb has been specifically designed for embedded systems and the typical requirements that accompany them, such as real-time capability and constraints on memory consumption. As a major advantage, low-level operations are hidden in the library which relieves software developers from the burden of thread management and synchronization. This not only improves productivity of parallel software development, but also results in increased reliability and performance of the applications.
\embb is independent of the hardware architecture (x86, ARM, ...) and runs on various platforms, from small devices to large systems containing numerous processor cores. It builds on MTAPI, a standardized programming interface for leveraging task parallelism in embedded systems containing symmetric or asymmetric multicore processors. A core feature of MTAPI is low-overhead scheduling of fine-grained tasks among the available cores during runtime. Unlike existing libraries, \embb supports task priorities, which allows the creation of soft real-time systems. Additionally, the scheduling strategy can be optimized for non-functional requirements such as minimal latency and fairness.
Besides the task scheduler, \embb provides basic parallel algorithms, concurrent data structures, and skeletons for implementing stream processing applications (see Figure~\ref{fig:introduction_embb_components}). These building blocks are largely implemented in a non-blocking fashion, thus preventing frequently encountered pitfalls like lock contention, deadlocks, and priority inversion. As another advantage in real-time systems, the algorithms and data structures give certain progress guarantees. For example, wait-free data structures guarantee system-wide progress which means that every operation completes within a finite number of steps independently of any other concurrent operations on the same data structure.
\begin{figure}[H]
\centering
\includegraphics[width=0.75\columnwidth]{../images/embb.pdf}
\label{fig:embb_components}
\caption{Main building blocks of \embb}
\label{fig:introduction_embb_components}
\end{figure}
% TODO
%\section{Key Features and Requirements}
\section{Outline}
The purpose of this tutorial is to introduce the basic concepts of \embb and to demonstrate typical application scenarios by means of simple examples. The tutorial is not intended to be complete in the sense that it describes every feature of \embb. For a detailed description of the API, please see the HTML documentation.
In the next subsection, we briefly describe the concept of function objects which is essential for using \embb. In Chapter~\ref{cha:mtapi}, we then present the task management features of MTAPI. These provide the basis for the algorithms outlined in Chapter~\ref{cha:algorithms} and the dataflow framework presented in Chapter~\ref{cha:dataflow}.
\section{Functions, Functors, and Lambdas}
\label{sec:introduction_function_objects}
Throughout this tutorial, we will encounter C++ types which model the C++ concept\footnote{In this context, the term \emph{concept} refers to a named set of requirements on a type.} \lstinline|FunctionObject|. The function object concept comprises function pointer, functor, and lambda types that are callable with suitable arguments by the function call syntax. Given a function object \lstinline|f| and arguments \lstinline|arg1|, \lstinline|arg2|, \lstinline|...|, the expression \lstinline|f(arg1, arg2, ...)| is a valid function invocation. If you are already familiar with function objects, you can safely skip the rest of this section. Otherwise, it might be worth reading it to get an idea of what is meant when talking about a function objects.
Consider, for example, the transformation of an iterable range of data values. Specifically, consider a vector of integers initialized as follows:
%
\\\inputlisting{../examples/stl_for_each/setup-snippet.h}
%
The range consists of the values (\lstinline|1, 2, 3, 4, 5|) and we now want to double each of them. We could simply get an iterator from the container holding the range, iterate over every element, and multiply it by two:
%
\\\inputlisting{../examples/stl_for_each/manual-snippet.h}
%
The range then contains the values (\lstinline|2, 4, 6, 8, 10|). In order to demonstrate the concept of function objects, we are now going to use the \lstinline|std::for_each| function defined in the \lstinline|algorithm| header of the C++ Standard Library. This function accepts as argument a \lstinline|UnaryFunction|, that is, a function object which takes only one argument. In case of \lstinline|std::for_each|, the argument has to have the same type as the elements in the range, as these are passed to the unary function. In our example, the unary function's task is to double the incoming value. We could define a function for that purpose:
%
\\\inputlisting{../examples/stl_for_each/function_define-snippet.h}
%
Since a function pointer models the concept of function objects, we can simply pass \lstinline|&DoubleFunction| to \lstinline|std::for_each|:
%
\\\inputlisting{../examples/stl_for_each/function-snippet.h}
%
Another possibility is to define a functor
%
\\\inputlisting{../examples/stl_for_each/functor_define-snippet.h}
%
and to pass an instance of this class to \lstinline|std::for_each|:
%
\\\inputlisting{../examples/stl_for_each/functor-snippet.h}
%
Functors as well as the function pointers separate the actual implementation from its place of usage which can be useful if the functionality is needed at different places. In many cases, however, it is advantageous to have the implementation of the function object at the same place as it is used. C++11 provides lambda expressions for that purpose which make our example more concise:
%
\\\inputlisting{../examples/stl_for_each/lambda-snippet.h}
%
Of course, this example is too simple to really benefit from function objects and the algorithms contained in the C++ Standard Library. However, in combination with the parallelization features provided by \embb, function objects are a helpful mechanism to boost productivity. Within this document, whenever a function object or one of its subtypes is required, one can use a function pointer, a functor, or a lambda. For simplicity, we will restrict ourselves to lambdas in subsequent examples, as they are most suitable for this kind of tutorial.
\chapter{MTAPI}
\label{cha:mtapi}
Leveraging the power of multicore processors requires to split computations into fine-grained tasks that can be executed in parallel. Threads are usually too heavy-weight for that purpose, since context switches consume a significant amount of time. Moreover, programming with threads is complex and error-prone due to typical pitfalls such as race conditions and deadlocks. To solve these problems, efficient task scheduling techniques have been developed which dynamically distribute the available tasks among a fixed number of worker threads. To reduce overhead, there is usually exactly one worker thread for each processor core.
While task schedulers are nowadays widely employed, especially in desktop and server applications, they are typically limited to a single operating system running on a homogeneous multicore processor. System-wide task management in heterogeneous embedded systems must be realized explicitly with low-level communication mechanisms. MTAPI~\cite{MTAPI} addresses those issues by providing an API which allows parallel embedded software to be designed in a straightforward way, covering homogeneous and heterogeneous multicore architectures, as well as acceleration units. It abstracts from the hardware details and lets software developers focus on the application. Moreover, MTAPI takes into account typical requirements of embedded systems such as real-time constraints and predictable memory consumption.
The remainder of this chapter is structured as follows: The next section explains the basic terms and concepts of MTAPI as given in the specification~\cite{MTAPI}. Section~\ref{sec:mtapi_c_interface} describes the C API using a simple example taken from~\cite{MTAPI}. Finally, Section~\ref{sec:mtapi_cpp_interface} outlines the use of MTAPI in C++ applications. Note that the C++ interface is provided by \embb for convenience but it is not part of the standard.
\section{Foundations}
\subsection{Domains}
An MTAPI system is composed of one or more MTAPI domains. An MTAPI domain is a unique system global entity. Each MTAPI domain comprises a set of MTAPI nodes. An MTAPI node may only belong to one MTAPI domain, while an MTAPI domain may contain one or more MTAPI nodes. This allows the programmer to use MTAPI domains as namespaces for all kinds of IDs (e.g., nodes, actions, queues, etc.).
\subsection{Nodes}
An MTAPI node is an independent unit of execution, such as a process, thread, thread pool, processor, hardware accelerator, or instance of an operating system. A given MTAPI implementation specifies what constitutes a node for that implementation.
The intent is to avoid a mixture of node definitions in the same implementation (or in different domains within an implementation). If a node is defined as a unit of execution with its private address space (like a process), then a core with a single unprotected address space OS is equivalent to a node, whereas a core with a virtual memory OS can host multiple nodes.
On a shared memory SMP processor, a node can be defined as a subset of cores. A quad-core processor, for example, could be divided into two nodes, one node representing three cores and one node representing the fourth core reserved exclusively for certain tasks. The definition of a node is flexible because this allows applications to be written in the most portable fashion supported by the underlying hardware, while at the same time supporting more general-purpose multicore and many-core devices.
The definition allows portability of software at the interface level (e.g., the functional interface between nodes). However, the software implementation of a particular node cannot (and often should not) necessarily be preserved across a multicore SoC product line (or across product lines from different silicon providers) because a given node's functionality may be provided in different ways, depending on the chosen multicore SoC.
\subsection{Tasks}
A task represents the computation associated with the data to be processed. A task is executed concurrently to the code starting the task. The main API functions are \lstinline|mtapi_task_start()| and \lstinline|mtapi_task_wait()|. The semantics are similar to the corresponding thread functions (e.g. \lstinline|pthread_create|$/$\lstinline|pthread_join| in Pthreads). The lifetime of a task is limited; it can be started only once.
\subsection{Actions}
In order to cope with heterogeneous systems and computations implemented in hardware, a task is not directly associated with an entry function as it is done in other task-parallel APIs. Instead, it is associated with at least one action object representing the calculation. The association is indirect: one or more actions implement a job, one job is associated with a task. If the action is implemented in software, this is either a function on the same node (which can represent the same processor or core) or a function implemented on a different node that does not share memory with the core starting the task.
Starting a task consists of three steps:
\begin{enumerate}
\item Create the action object with a job ID (software-implemented actions only).
\item Obtain a job reference.
\item Start the task using the job reference.
\end{enumerate}
\subsection{Synchronization}
The basic synchronization mechanism provided with in MTAPI is waiting for task completion. Calling \lstinline|mtapi_task_wait()| with a task handle blocks the current thread or task until the task referenced by the handle has completed. Depending on the implementation, the calling thread can be used for executing other tasks while waiting for the task to be completed. In order to synchronize with a set of tasks, every task can be associated with a task group. The methods \lstinline|mtapi_group_wait_all()| and \lstinline|mtapi_group_wait_any()| wait for a group of tasks or completion of any task in the group, respectively.
%MTAPI only provides synchronization on task granularity. Synchronization inside a task implementation can be done by MCAPI messages, MRAPI synchronization primitives, and the MRAPI memory primitives. If MCAPI or MRAPI implementations are not available, synchronization mechanisms provided by the operating system or a threading library must be used. In this case, the MTAPI implementation must define the consequences of using those mechanisms in the task context.
\subsection{Queues}
Queues are used for guaranteeing sequential order of execution of tasks. A common use case is packet processing in the communication domain: for every connection all packets must be processed sequentially, while the packets of different connections can be processed in parallel to each other.
Sequential execution is accomplished by using a queue for every connection and queuing all packets of one connection into the same queue. In some systems, queues are implemented in hardware, otherwise MTAPI implements software queues. MTAPI is designed for handling thousands of queues that are processed in parallel.
The procedure for setting up and using a queue is as follows:
\begin{enumerate}
\item Create the action object (software-implemented actions only).
\item Obtain a job reference.
\item Create a queue object and attach the job to the queue (software-implemented queues only).
\item Obtain a queue handle if the queue was created on a different node, or if the queue is hardware-implemented.
\item Use the queue: enqueue the work using the queue.
\end{enumerate}
Another important purpose of queues is that different queues can express different scheduling attributes for the same job. For example, in contrast to order-preserving queues, non-order-preserving queues can be used for load-balancing purposes between different computation nodes. In this case, the queue must be associated with more than one action implementing the same task on different nodes (i.e., different processors or cores implementing different instruction set architectures). If a queue is configured this way, the order will not be preserved.
\subsection{Attributes}
Attributes are provided as a means to extend the API. Different implementations may define and support additional attributes beyond those predefined by the API. To promote portability and implementation flexibility, attributes are maintained in an opaque data object that may not be directly examined by the user. Each object (e.g., task, action, queue) has an attributes data object associated with it, and many attributes have a small set of predefined values that must be supported by MTAPI implementations. The user may initialize, get, and set these attributes. For default behavior, it is not necessary to call the initialize, get, and set attribute functions. However, to get non-default behavior, the typical four-step process is:
\begin{enumerate}
\item Declare an attributes object of the \lstinline|mtapi_<object>_attributes_t| data type.
\item \lstinline|mtapi_<object>attr_init()|: Returns an attributes object with all attributes set to their default values.
\item \lstinline|mtapi_<object>attr_set()|: (Repeat for all attributes to be set). Assigns a value to the specified attribute of the specified attributes object.
\item \lstinline|mtapi_<object>_create()|: Passes the attributes object modified in the previous step as a parameter when creating the object.
\end{enumerate}
At any time, the user can call \lstinline|mtapi_<object>_get_attribute()| to query the value of an attribute. After an object has been created, some objects allow to change attributes by calling \lstinline|mtapi_<object>_set_attribute()|.
\section{C Interface}
\label{sec:mtapi_c_interface}
The calculation of Fibonacci numbers is a simple example for a recursive algorithm that can easily be parallelized. Listing~\ref{lst:mtapi_fibonacci_sequential} shows a sequential version.
\begin{lstlisting}[frame=none,caption={Sequential program for computing Fibonacci numbers},label={lst:mtapi_fibonacci_sequential}]
int fib(int n) {
int x,y;
if (n < 2) {
return n;
} else {
x = fib(n - 1);
y = fib(n - 2);
return x + y;
}
}
int fibonacci(int n) {
return fib(n);
}
void main(void) {
int n = 6;
int result = fibonacci(n);
printf("fib(%i) = %i\n", n, result);
}
\end{lstlisting}
This algorithm can be parallelized by spawning a task for one of the recursive calls (\lstinline|fib(n - 1)|, for example). When doing this with MTAPI, an action function that represents \lstinline|fib(int n)| is needed. It has the following signature:
%
\\\inputlisting{../examples/mtapi/mtapi_c_action_signature-snippet.h}
%
Within the action function, the arguments should be checked, since the user might supply a buffer that is too small:
%
\\\inputlisting{../examples/mtapi/mtapi_c_validate_arguments-snippet.h}
%
Here, \lstinline|mtapi_context_status_set()| is used to report errors. The error code will be returned by \lstinline|mtapi_task_wait()|. Also, care has to be taken when using the result buffer. The user might not want to use the result and supply a NULL pointer or accidentally a buffer that is too small:
%
\\\inputlisting{../examples/mtapi/mtapi_c_validate_result_buffer-snippet.h}
%
At this point, calculation of the result can commence. First, the terminating condition of the recursion is checked:
%
\\\inputlisting{../examples/mtapi/mtapi_terminating_condition-snippet.h}
%
After that, the first part of the computation is launched as a task using \lstinline|mtapi_task_start()| (the action function is registered with the job \lstinline|FIBONACCI_JOB| in the \lstinline|fibonacci()| function and the resulting handle is stored in the global variable \lstinline|mtapi_job_hndl_t fibonacciJob|):
%
\\\inputlisting{../examples/mtapi/mtapi_c_calc_task-snippet.h}
%
The second part can be executed directly:
%
\\\inputlisting{../examples/mtapi/mtapi_c_calc_direct-snippet.h}
%
Then, completion of the MTAPI task has to be waited for by calling \lstinline|mtapi_task_wait()|:
%
\\\inputlisting{../examples/mtapi/mtapi_c_wait_task-snippet.h}
%
Finally, the results can be added and written into the result buffer:
%
\\\inputlisting{../examples/mtapi/mtapi_write_back-snippet.h}
%
The \lstinline|fibonacci()| function gets a bit more complicated now. The MTAPI runtime has to be initialized first by (optionally) initializing node attributes and then calling \lstinline|mtapi_initialize()|:
%
\\\inputlisting{../examples/mtapi/mtapi_c_initialize-snippet.h}
%
Then, the action function needs to be associated to a job. By calling \lstinline|mtapi_action_create()|, the action function is registered with the job \lstinline|FIBONACCI_JOB|. The job handle of this job is stored in the global variable \lstinline|mtapi_job_hndl_t fibonacciJob| so that it can be accessed by the action function later on:
%
\\\inputlisting{../examples/mtapi/mtapi_c_register_action-snippet.h}
%
Now that the action is registered with a job, the root task can be started with \lstinline|mtapi_task_start()|:
%
\\\inputlisting{../examples/mtapi/mtapi_c_start_task-snippet.h}
%
%The started task has to be waited for before the result can be returned.
After everything is done, the action is deleted (\lstinline|mtapi_action_delete()|) and the runtime is shut down (\lstinline|mtapi_finalize()|):
%
\\\inputlisting{../examples/mtapi/mtapi_c_finalize-snippet.h}
%
\section{C++ Interface}
\label{sec:mtapi_cpp_interface}
\embb provides C++ wrappers for the MTAPI C interface. The signature of the action function for the C++ interface is the same as in the C interface:
%
\\\inputlisting{../examples/mtapi/mtapi_c_action_signature-snippet.h}
%
Checking argument and result buffer sizes is the same as in the C example. Also, the terminating condition of the recursion still needs to be checked:
%
\\\inputlisting{../examples/mtapi/mtapi_terminating_condition-snippet.h}
%
After that, the first part of the computation is launched as an MTAPI task using \lstinline|embb::mtapi::Node::Start()| (the action function is registered with the job \lstinline|FIBONACCI_JOB| in the \lstinline|fibonacci()| function and the resulting handle is stored in the global variable \lstinline|embb::mtapi::Job fibonacciJob|):
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_calc_task-snippet.h}
%
The second part can be executed directly:
%
\\\inputlisting{../examples/mtapi/mtapi_c_calc_direct-snippet.h}
%
Then, completion of the MTAPI task has to be waited for using \lstinline|embb::mtapi::Task::Wait()|:
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_wait_task-snippet.h}
%
Finally, the two parts can be added and written into the result buffer:
%
\\\inputlisting{../examples/mtapi/mtapi_write_back-snippet.h}
%
Note that there is no need to do error checking everywhere, since errors are reported as exceptions. In this example there is only a single try/catch block in the main function:
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_main-snippet.h}
%
The \lstinline|fibonacci()| function is about the same as in the C version. The MTAPI runtime needs to be initialized first:
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_initialize-snippet.h}
%
Then the node instance can to be fetched:
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_get_node-snippet.h}
%
After that, the action function needs to be associated to a job. By instancing an \lstinline|embb::mtap::Action| object, the action function is registered with the job \lstinline|FIBONACCI_JOB|. The job is stored in the global variable \lstinline|embb::mtapi::Job fibonacciJob| so that it can be accessed by the action function later on:
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_register_action-snippet.h}
%
Not that the action is registered and the job is initialized, the root task can be started:
%
\\\inputlisting{../examples/mtapi/mtapi_cpp_start_task-snippet.h}
%
Again, the started task has to be waited for (using \lstinline|embb::mtapi::Task::Wait()|) before the result can be returned.
The registered action will be unregistered when it goes out of scope.
The runtime needs to be shut down by calling:
\\\inputlisting{../examples/mtapi/mtapi_cpp_finalize-snippet.h}
\section{Plugins}
The \embb implementation of MTAPI provides an extension to allow for custom actions that are not executed by the scheduler for software actions as detailed in the previous sections.
Two plugins are delivered with \embb, one for supporting distributed systems through TCP/IP networking and the other to allow for transparently using OpenCL accelerators.
\subsection{Plugin API}
The plugin API consists of a single function named \lstinline|mtapi_ext_plugin_action_create()| contained in the mtapi\_ext.h header file. It is used to associate the plugin action with a specific job ID:
\begin{lstlisting}
mtapi_action_hndl_t mtapi_ext_plugin_action_create(
MTAPI_IN mtapi_job_id_t job_id,
MTAPI_IN mtapi_ext_plugin_task_start_function_t task_start_function,
MTAPI_IN mtapi_ext_plugin_task_cancel_function_t task_cancel_function,
MTAPI_IN mtapi_ext_plugin_action_finalize_function_t action_finalize_function,
MTAPI_IN void* plugin_data,
MTAPI_IN void* node_local_data,
MTAPI_IN mtapi_size_t node_local_data_size,
MTAPI_IN mtapi_action_attributes_t* attributes,
MTAPI_OUT mtapi_status_t* status
);
\end{lstlisting}
The plugin action is implemented through 3 callbacks, task start, task cancel and action finalize.
\lstinline|task_start_function| is called when the user requests execution of the plugin action by calling \lstinline|mtapi_task_start()| or \lstinline|mtapi_task_enqueue()|. To those functions the fact that they operate on a plugin action is transparent, they only require the job handle of the job the action was registered with.
\lstinline|task_cancel_function| is called when the user requests cancelation of a tasks by calling \lstinline|mtapi_task_cancel()| or by calling \lstinline|mtapi_queue_disable()| on a non-retaining queue.
\lstinline|action_finalize_function| is called when the node is finalized and the action is deleted, or when the user explicitly deletes the action by calling \lstinline|mtapi_action_delete()|.
For illustration our example plugin will provide a no-op action. The task start callback in that case looks like this:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_start_cb-snippet.h}
%
The scheduling operation is responsible for bringing the task to execution, this might involve instructing some hardware to execute the task or pushing the task into a queue for execution by a separate worker thread. Here however, the task is executed directly:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_schedule-snippet.h}
%
Since the task gets executed right away, it cannot be canceled and the task cancel callback implementation is empty:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_cancel_cb-snippet.h}
%
The plugin action did not acquire any resources so the action finalize callback is empty as well:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_action_finalize_cb-snippet.h}
%
Now that the callbacks are in place, the action can be registered with a job after the node was initialized using \lstinline|mtapi_initialize()|:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_action_create-snippet.h}
%
The job handle can now be obtained the normal MTAPI way. The fact that there is a plugin working behind the scenes is transparent by now:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_get_job-snippet.h}
%
Using the job handle tasks can be started like normal MTAPI tasks:
%
\\\inputlisting{../examples/mtapi/mtapi_c_plugin_task_start-snippet.h}
%
This call will lead to the invocation of then \lstinline|plugin_task_start| callback function, where the plugin implementor is responsible for bringing the task to execution.
\subsection{Network}
The MTAPI network plugin provides a means to distribute tasks over a TCP/IP network. As an example the following vector addition action is used:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_action_function-snippet.h}
%
It adds two float vectors and a float from node local data and writes the result into the result float vector. In the example code the vectors will hold \lstinline|kElements| floats each.
To use the network plugin, its header file needs to be included first:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_header-snippet.h}
%
After initializing the node using \lstinline|mtapi_initialize()|, the plugin itself needs to be initialized:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_plugin_initialize-snippet.h}
%
This will set up a listening socket on the localhost interface (127.0.0.1) at port 12345. The socket will allow a maximum of 5 connections and have a maximum transfer buffer size of \lstinline|kElements * 4 * 3 + 32|. This buffer size needs to be big enough to fit at least the argument and result buffer sizes at once. The example uses 3 vectors of \lstinline|kElements| floats using \lstinline|kElements * sizeof(float) * 3| bytes.
Since the example connects to itself on localhost, the "remote" action needs to be registered with the \lstinline|NETWORK_REMOTE_JOB|:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_remote_action_create-snippet.h}
%
After that, the local network action is created, that maps \lstinline|NETWORK_LOCAL_JOB| to \lstinline|NETWORK_REMOTE_JOB| through the network:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_local_action_create-snippet.h}
%
Now, \lstinline|NETWORK_LOCAL_JOB| can be used to execute tasks by simply calling \lstinline|mtapi_task_start()|. Their parameters will be transmitted through a socket connection and are consumed by the network plugin worker thread. The thread will start a task using the \lstinline|NETWORK_REMOTE_JOB|. When this task is finished, the results will be collected and sent back through the network. Again the network plugin thread will receive the results, provide them to the \lstinline|NETWORK_LOCAL_JOB| task and mark that task as finished.
When all work is done, the plugin needs to be finalized. This will stop the plugin worker thread and close the sockets:
%
\\\inputlisting{../examples/mtapi/mtapi_network_c_plugin_finalize-snippet.h}
%
Then the node may be finalized by calling \lstinline|mtapi_finalize()|.
\subsection{OpenCL}
The MTAPI OpenCL plugin allows the user to incorporate the computational power of an OpenCL accelerator, if one is available in the system.
The vector addition example from the network plugin is used again. However, the action function is an OpenCL kernel now:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_kernel-snippet.h}
%
The OpenCL plugin header file needs to be included first:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_header-snippet.h}
%
As with the network plugin, the OpenCL plugin needs to be initialized after the node has been initialized:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_plugin_initialize-snippet.h}
%
Then the plugin action can be registered with the \lstinline|OPENCL_JOB|:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_action_create-snippet.h}
%
The kernel source and the name of the kernel to use (AddVector) need to be specified while creating the action. The kernel will be compiled using the OpenCL runtime and the provided node local data transferred to accelerator memory. The local work size is the number of threads that will share OpenCL local memory, in this case 32. The element size instructs the OpenCL plugin how many bytes a single element in the result buffer consumes, in this case 4, as a single result is a single float. The OpenCL plugin will launch \lstinline|result_buffer_size/element_size| OpenCL threads to calculate the result.
Now the \lstinline|OPENCL_JOB| can be used like a normal MTAPI job to start tasks.
After all work is done, the plugin needs to be finalized. This will free all memory on the accelerator and delete the corresponding OpenCL context:
%
\\\inputlisting{../examples/mtapi/mtapi_opencl_c_plugin_finalize-snippet.h}
%
\sectionnonum{Intended Audience}
This document is intended for software developers who want to get an introduction to \embb and an idea on how to use its functionalities. It is not an API reference.
\sectionnonum{Objectives}
The objective of this document is to give an idea on how to use the functionalities of the \embb to solve simple programming problems.
\sectionnonum{Structure}
Structure
\ No newline at end of file
\chapter{Tasks}
\label{cha:tasks}
\embb provides a simple task management wrapper for the MTAPI interface. Using the example from the previous section, the signature of the action function for the tasks interface looks like this:
%
\\\inputlisting{../examples/tasks/tasks_cpp_action_signature-snippet.h}
%
First, the node instance needs to be obtained. If the node is not initialized yet, this function will do it.
%
\\\inputlisting{../examples/tasks/tasks_cpp_get_node-snippet.h}
%
\emph{\textbf{Note:} Automatic initialization allows for easy usage of the \emph{Algorithms} and \emph{Dataflow} building blocks. For performance measurements however, explicit initialization by calling \lstinline|embb::tasks::Node::Initialize| is imperative since the measurements will otherwise include the initialization time of MTAPI.}
Checking the arguments and the result buffer is not necessary, since everything is safely typed. However, the terminating condition of the recursion still needs to be checked:
%
\\\inputlisting{../examples/mtapi/mtapi_terminating_condition-snippet.h}
%
After that, the first part of the computation is launched as an MTAPI task using \lstinline|embb::tasks::Node::Spawn()| (registering an action function with a job is done automatically):
%
\\\inputlisting{../examples/tasks/tasks_cpp_calc_task-snippet.h}
%
The second part can be executed directly:
%
\\\inputlisting{../examples/tasks/tasks_cpp_calc_direct-snippet.h}
%
Then, completion of the MTAPI task has to be waited for using \lstinline|embb::tasks::Task::Wait()|:
%
\\\inputlisting{../examples/tasks/tasks_cpp_wait_task-snippet.h}
%
Finally, the two parts can be added and written into the result buffer:
%
\\\inputlisting{../examples/mtapi/mtapi_write_back-snippet.h}
%
The \lstinline|fibonacci()| function also gets simpler compared to the C version. The MTAPI runtime is initialized automatically, only the node instance has to be fetched:
%
\\\inputlisting{../examples/tasks/tasks_cpp_get_node-snippet.h}
%
The root task can be started using \lstinline|embb::tasks::Node::Spawn()| directly, registering with a job is done automatically:
%
\\\inputlisting{../examples/tasks/tasks_cpp_start_task-snippet.h}
%
Again, the started task has to be waited for (using \lstinline|embb::tasks::Task::Wait()|) before the result can be returned. The runtime is shut down automatically in an \lstinline|atexit()| handler.
\emph{\textbf{Note:} If the node was initialized explicitly by calling \lstinline|embb::tasks::Node::Initialize|, the runtime must also be shut down explicitly by calling \lstinline|embb::tasks::Node::Finalize|.}
% ===================================
% document formatting refinement
% ===================================
% No indents for whole text
\setlength{\parindent}{0pt}
% improve the line breaking
\setlength{\emergencystretch}{1em}
% pic width = \textwidth - \chapterpicwidth
\def\chapterpicwidth{0.43}
% line breaks for URLs
\renewcommand{\UrlBreaks}{\do\/}
%
% custom hyphenation
%
\hyphenation{in-stru-men-ta-tion analy-sis con-cur-ren-cy}
% ===================================
% settings for the listings package
% ===================================
\definecolor{lightGray}{RGB}{242,242,242}
\lstset{
language=C++,
basicstyle=\ttfamily,
columns=fullflexible,
keepspaces=true, % To have spaces monsized
tabsize=2,
frame=none, % = single
breaklines=true,
numbers=left,
numberstyle=\tiny,
escapeinside={//@}{@},
showstringspaces=false,
resetmargins=true,
xleftmargin=18pt,
xrightmargin=0pt,
%resetmargins=true,
%framextopmargin=0pt
backgroundcolor=\color{lightGray},
captionpos=b,
%abovecaptionskip=0pt,
%belowcaptionskip=0pt,
%aboveskip=3pt,
%belowskip=0pt,
%framesep=1pt,
numberbychapter=false,
}
% coloring for listings
\lstdefinestyle{colored}{
moredelim=[is][\color{blue}]{@}{@},
moredelim=[is][\color{red}]{|}{|},
}
%
% Counter and caption for listings
%
%\newcounter{lstlisting} % already defined by pkg listing at \begin{document}
\counterwithout{lstlisting}{chapter}
\newcommand{\inputlisting}[1]{
\begin{minipage}{\columnwidth}
\lstinputlisting{#1}
\end{minipage}
}
\newcommand{\lstgname}{Listing}
\newcommand{\listingcaption}[1]%
{%
{%
\refstepcounter{lstlisting}
\noindent\footnotesize{\lstgname~\thelstlisting{:}~#1\hfill}
}%
}%
% ===========================
% cover generation commands
% ===========================
\def\backcover{
\genbackpage{
\textbf{Siemens AG}\newline
Corporate Technology\newline
Multicore Expert Center\newline
\newline
Otto-Hahn-Ring 6\newline
81739 Muenchen\newline
Germany\newline
\newline
{http://multicore.ct.siemens.de}
}
}
% ======================
% convenience commands
% ======================
\def\chaptername{Chapter}
\def\algname{Algorithm}
\def\sectionname{Section}
%
% Programming languages and frameworks
%
\def\qt{Qt}
\def\cE{C11}
\def\cpp{C\raisebox{0.17ex}{\small\textbf{++}}}
\def\cppFootnote{C\raisebox{0.08ex}{\small{++}}}
\def\cppE{{\cpp}11}
\newcommand{\csharp}{%
{\settoheight{\dimen0}{C}C\kern-.05em\hspace{0.5pt}\resizebox{!}{\dimen0}{\raisebox{\depth}{\#}}}}
\def\dotnet{.NET}
%
% Special characters
%
\def\myCheck{\ding{51}} % check
\def\myCross{\ding{55}} % cross
%
% Various stuff
%
\def\time#1{#1}
\def\markup#1{{\color{NavyBlue}#1}}
\newcommand{\toolcard}[9]{
\begin{table}
\caption{Quick card for {#2}}
{\small
\begin{tabular}{>{\bfseries}p{0.295\columnwidth}p{0.605\columnwidth}}
\thickhline
{Tool} & #2 \\
{Detectable bugs} & #3 \\
{License} & #4 \\
{Platforms} & #5 \\
{Operating systems} & #6 \\
{\mbox{Languages}} & #7 \\
{Threading libraries} & {#8} \\
{Additional facts} & {#9} \\
\thickhline
\end{tabular}
}
\label{qc:#1}
\end{table}
}
% table cell that allows line breaks (e.g., for toolcard)
% first (optional) parameter defines alignment (l,c,r)
% second parameter is the content
\def\lbcell[#1]#2{\rule{0pt}{4ex}\shortstack[#1]{#2}}
% =======================
% other (various) stuff
% =======================
%
% very custom stuff
%
\def\hb#1{\hbImpl(#1)}
\def\hbRel{\rightarrow}
\def\hbImpl(#1,#2){$#1 \hbRel #2$}
@manual{MTAPI,
title = {Multicore Task Management API (MTAPI) Specification V1.0},
organization = {The Multicore Association},
year = 2013,
month = mar
}
Copyright (C) nemadesign GbR
$Rev: 80 $
$Date: 2014-09-08 21:22:10 +0200 (Mo, 08. Sep 2014) $
Things to consider
==================
In case of a wrong linf for the 'Bilbiography'
entry, add this before the '\addcontentsline{toc}{...}{...}:
Example:
-------- BEGIN ---------
\cleardoublepage
\phantomsection
% generate TOC
\addcontentsline{toc}{chapter}{Bibliography}
--------- END ----------
New macros
==========
\chapterpictopnum{_TEXT_}{_PIC_}{_WIDTH_}{_LABEL_}
\chapterpictopnonum{_TEXT_}{_PIC_}{_WIDTH_}{_LABEL_}
Add picture above chapter title
_TEXT_ : title for the chapter
_PIC_ : image file
_WIDTH_ : relative width of text (1.0 equals text width)
_LABEL_ : name for the label of the chapter
Examples:
\chapterpicnum{Das Kapitel}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.5}
\chapterpicnonum{text text text}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.3}
______________________________________________________________________________________
\chapterpicrightnum{_TEXT_}{_PIC_}{_WIDTH_}{_LABEL_}
\chapterpicrightnonum{_TEXT_}{_PIC_}{_WIDTH_}{_LABEL_}
Add picture right to chapter title
_TEXT_ : title for the chapter
_PIC_ : image file
_WIDTH_ : relative width of text (1.0 equals text width)
_LABEL_ : name for the label of the chapter
Examples:
\chapterpicrightnum{Chapter with Picture}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.5}
\chapterpicrightnonum{Chapter* with Picture}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.4}
______________________________________________________________________________________
\chapterpicteasernum{_TEXT_}{_PIC_}{_WIDTH_}{_LABEL_}{_TEASE_}
\chapterpicteasernonum{_TEXT_}{_PIC_}{_WIDTH_}{_LABEL_}{_TEASE_}
Chapter title with picture and teaser text.
In single column layout: white teaser text in grey box.
In double column layout: grey teaser text in white box.
_TEXT_ : title for the chapter
_PIC_ : image file
_WIDTH_ : relative width of text (1.0 equals text width)
_LABEL_ : name for the label of the chapter
_TEASE_ : teaser text
Examples:
\chapterpicteasernum{Chapter \& Picture \& Teaser}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.5}{Text}
\chapterpicteasernonum{Chapter* \& Picture \& Teaser}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.4}{Text}
______________________________________________________________________________________
\tableofcontentspic{_TEXT_}{_PIC_}{_WIDTH_}
Add table of contents with picture
_TEXT_ : title for the chapter
_PIC_ : tmage file
_WIDTH_ : relative width of text (1.0 equals text width)
Example:
\tableofcontentspic{Contents}{gfx/siemens-logo-wallpaper-1024x597.jpg}{0.5}
______________________________________________________________________________________
\gentitlepage{_PIC_}{_TEXT1_}{_TEXT2_}
Generate a titlepage
_PIC_ : image file (must be of square dimensions!)
_TEXT1_ : text above title
_TEXT2_ : text for title
Example:
\gentitlepage{gfx/Infineon-Baseband-Chip-X618.jpg}{Some text here}{Very long title for this Document Over Two Lines}
______________________________________________________________________________________
\gentitlepagenopic{_TEXT1_}{_TEXT2_}
Generate a titlepage without a picture
_TEXT1_ : text above title
_TEXT2_ : text for title
Example:
\gentitlepagenopic{Some text here}{Very long title for this Document Over Two Lines}
______________________________________________________________________________________
\genbackpage{_TEXT_}
Generate a backpage
_TEXT_ : white text
Example:
\genbackpage{Siemens AG}
______________________________________________________________________________________
\renewcommand{\shorttitle}{_TEXT_}
Set short title in header
_TEXT_ : text for short title
Example:
\renewcommand{\shorttitle}{Short title for paper}
______________________________________________________________________________________
\renewcommand{\shortdate}{_TEXT_}
Set date in short title
_TEXT_ : text for date in short title, default is \today
Example:
\renewcommand{\shortdate}{\today}
\renewcommand{\shortdate}{11.09.2011}
______________________________________________________________________________________
\renewcommand{\copyrightdate}{_TEXT_}
Set date in short title
_TEXT_ : text for date in copyright line on last page ,default is \today
Example:
\renewcommand{\copyrightdate}{\today}
\renewcommand{\copyrightdate}{11.09.2011}
______________________________________________________________________________________
Used LaTeX packages
===================
\usepackage[colorlinks=true, bookmarks=false]{hyperref}
\usepackage[scaled]{uarial}
\usepackage[T1]{fontenc}
%\usepackage[ngerman]{babel}
\usepackage[english]{babel}
\usepackage{amsmath}
\usepackage[pdftex]{graphicx}
\usepackage{multirow}
\usepackage{subfigure}
\usepackage{listings}
\usepackage{courier}
\usepackage{titlesec}
\usepackage{scrpage2}
\usepackage{chngcntr}
\usepackage[table,usenames,dvipsnames]{xcolor}
\usepackage{booktabs}
\usepackage{color}
\usepackage{longtable}
\usepackage{colortbl}
\usepackage{fp}
\usepackage{eso-pic,picture}
\usepackage[absolute]{textpos}
\usepackage{multicol}
\usepackage{titletoc}
\usepackage{moresize}
\usepackage{printlen}
\usepackage{setspace}
\usepackage[colorlinks=true, bookmarks=false]{hyperref}
These packages are only used in the demo documents:
\usepackage{layout}
\usepackage{lipsum}
% Copyright (C) nemadesign GbR
% $Rev: 56 $:
% $Date: 2014-09-20 13:52:19 +0200 (Sa, 20. Sep 2014) $:
% This file contains settings and macros which are used in
% all variants for the siemens stylesheets
\usepackage[scaled]{uarial} % Font is Arial
\fontfamily{phv}\fontseries{m}\fontshape{n}\selectfont % Arial for Headings
\setkomafont{sectioning}{\sffamily\bfseries}
\renewcommand{\familydefault}{\sfdefault}
\usepackage[T1]{fontenc}
%\usepackage[ngerman]{babel}
\usepackage[english]{babel}
\usepackage{amsmath}
\usepackage[pdftex]{rotating,graphicx}
\usepackage{multirow}
\usepackage{layout}
\usepackage{lipsum}
\usepackage{subfigure}
\usepackage{multicol,listings}
\usepackage{courier}
\usepackage[automark]{scrpage2}
\usepackage{titlesec}
\usepackage{scrpage2}
\usepackage{chngcntr}
\usepackage[table,usenames,dvipsnames]{xcolor}
\usepackage{booktabs}
\usepackage{color}
\usepackage{longtable}
\usepackage{colortbl}
\usepackage{fp}
\usepackage{eso-pic,picture}
\usepackage[absolute]{textpos}
\usepackage{multicol}
\usepackage{cite}
\usepackage{titletoc}
\usepackage{moresize}
\usepackage{printlen}
\usepackage{setspace}
% Siemens specific packages
\usepackage[plain]{algorithm}
\usepackage{algorithmic}
\usepackage{array} % for tabular
\usepackage{pifont} % for \myCheck, \myCross
\usepackage[hyphens]{url}
\usepackage[hidelinks]{hyperref} % hyperref without colored links
\usepackage{balance} % for balancing the bibliography
\usepackage{ifthen}
% set title and date in headline
\newcommand{\shorttitle}{Default short title}
\newcommand{\shortdate}{\today}
\newcommand{\copyrightdate}{\today}
% nobody likes Hurenkinder und Schusterjungen
\hyphenpenalty = 500
\tolerance = 800
\widowpenalty = 300
\clubpenalty = 300
\displaywidowpenalty = 10000
% change table background colors
\definecolor{lightgray}{gray}{0.9}
\let\oldtabular\tabular
\let\endoldtabular\endtabular
\renewenvironment{tabular}{\rowcolors{2}{white}{lightgray}\oldtabular}{\endoldtabular}
% thick hline in tables
\newcommand{\thickhline}{%
\noalign {\ifnum 0=`}\fi \hrule height 1pt
\futurelet \reserved@a \@xhline
}
% global counters for tables and figures
\counterwithout{figure}{chapter}
\counterwithout{table}{chapter}
\counterwithout{footnote}{chapter}
% left align captions
\usepackage[
singlelinecheck=false % <-- important
]{caption}
% No title for TOC
\renewcommand*{\tocbasic@listhead}[1]{%
\typeout{Ueberschrift ``#1'' nicht ausgeben}%
}
\pagestyle{scrheadings}
% set headline and footline
\lehead{}
\lohead{}
\cehead{}
\cohead{}
\rehead{\shorttitle \;| \shortdate}
\rohead{\shorttitle \;| \shortdate}
\lefoot{Unrestricted \copyright \; Siemens AG \the\year. All rights reserved.}
\lofoot{Unrestricted \copyright \; Siemens AG \the\year. All rights reserved.}
\cefoot{}
\cofoot{}
\refoot{\thepage}
\rofoot{\thepage}
%\pagestyle{scrheadings}
\deftripstyle{myemptypage}{}{}{}{\thepage}{}{}
\KOMAoptions{cleardoublepage=myemptypage}
% headings and footings for chapter
\renewcommand{\chapterpagestyle}{scrheadings}
% no gap at beginning of chapter
\renewcommand*{\chapterheadstartvskip}{\vspace*{-\topskip}}
% small gap at the end of chapter
\renewcommand*{\chapterheadendvskip}{\vspace{3.0\baselineskip}}
% color definition
\definecolor{orange}{rgb}{0.92,0.47,0.04} % HEX 235 120 10
\definecolor{grey1}{rgb}{0.53,0.61,0.67} % HEX 135 155 170
\definecolor{grey2}{rgb}{0.31,0.39,0.45} % HEX 80 100 115
% font style for listings
\lstset{basicstyle=\footnotesize\ttfamily,breaklines=true}
\lstset{framextopmargin=0pt,frame=single}
% stripped pagewidth for title page
\newcommand{\Pw}{\strip@pt\paperwidth}
% sytle for LOF
\addtocontents{lof}{\protect\vspace{0pt}}
\renewcommand*\l@figure{\mdseries\bprot@dottedtocline{1}{0em}{3.0em}}
% shift everything up
\newcommand{\squeezeup}{\vspace{-5mm}}
\titlespacing*{\chapter}{0pt}{0pt}{40pt}
\addtokomafont{sectioning}{\color{orange}}
\def\thespread{30}
\addtokomafont{chapter}{\fontsize{28pt}{1.0}\linespread{\thespread}\selectfont}
\setkomafont{pagehead}{
\normalfont\sffamily}
\setkomafont{pagefoot}{
\normalfont\sffamily}
\setkomafont{pagenumber}{
\normalfont\sffamily}
\addtokomafont{pagenumber}{\color{grey1}}
\addtokomafont{pagefoot}{\color{grey1}}
\addtokomafont{pagehead}{\color{grey1}}
% Make nicer table and figure captions
\setkomafont{captionlabel}{\sffamily\bfseries}
\setkomafont{caption}{\sffamily}
% same identation for all lines in footnotes
\deffootnote{1em}{1em}{\thefootnotemark\ }
% Set first row for tables to bold text
\newcolumntype{$}{>{\global\let\currentrowstyle\relax}}
\newcolumntype{^}{>{\currentrowstyle}}
\newcommand{\rowstyle}[1]{\gdef\currentrowstyle{#1}%
#1\ignorespaces
}
% Macros by nemadesign
\setlength{\fboxsep}{0pt}
\setlength\fboxrule{0.1pt}
\newcommand{\moveup}{\vspace{-7mm}}
\newcommand{\movedown}{\vspace{10mm}}
\newcommand{\picgap}{\vspace{8mm}}
\newcommand{\picgapsmall}{\vspace{0mm}}
% Macros by Siemens
\newcommand{\printAuthors}[2][\empty]
{
\clearpage % this is important
\begin{minipage}[b][\textheight]{\textwidth}
\begin{oldtabular}{rp{0.8\columnwidth}}
\multicolumn{2}{l}{Authors} \\
& #2
\end{oldtabular}
\ifthenelse{\equal{#1}{\empty}}
{\empty}
{
\begin{oldtabular}{rp{0.8\columnwidth}}
\\
\multicolumn{2}{l}{Contributors} \\
& #1
\end{oldtabular}
} \\
\end{minipage}
\clearpage % this is important
}
% Copyright (C) nemadesign GbR
% $Rev: 56 $:
% $Date: 2014-09-02 21:28:49 +0200 (Di, 02. Sep 2014) $:
% definitions for two column style sheet
\makeatletter
\usepackage{sty/siemens_core}
\usepackage{geometry}
\geometry
{
left=1.8cm, %linker Seitenrand
right=1.8cm, %rechter Seitenrand
top=25mm, %oben der Abstand
bottom=28mm %Unten der Abstand
}
\renewcommand\section{\@startsection
{section}{1}{0mm} % name, ebene, einzug
{1.5\baselineskip} % vor-abstand
{0.3\baselineskip} % nach-abstand
{\bfseries\sffamily\Large\color{orange}} % layout
}
\renewcommand\subsection{\@startsection
{subsection}{2}{0mm}
{1.0\baselineskip}
{0.2\baselineskip}
{\bfseries\sffamily\Large\color{grey1}}
}
\newcommand\sectionnonum{\@startsection
{section}{1}{0mm}
{1.5\baselineskip}
{0.3\baselineskip}
{\normalfont\Large\bfseries\color{orange}}*}
\newcommand\subsectionnonum{\@startsection
{subsection}{2}{0mm}
{1.0\baselineskip}
{0.2\baselineskip}
{\bfseries\sffamily\Large\color{grey1}}*}
% TOC without indents
% add space before TOC
\addtocontents{toc}{\protect\vspace{100pt}}
\renewcommand*{\@dotsep}{0.5}
\renewcommand*\l@chapter{\bfseries\bprot@dottedtocline{1}{6em}{3.0em}}
\renewcommand*\l@section{\mdseries\bprot@dottedtocline{2}{6em}{3.0em}}
\renewcommand*\l@subsection{\mdseries\bprot@dottedtocline{3}{6em}{3.0em}}
\renewcommand*\l@subsubsection{\mdseries\bprot@dottedtocline{4}{6em}{3.0em}}
% gap between columns
\setlength{\columnsep}{12mm}
% gap between paragraphs
\setlength{\parskip}{0pt}
\def\chapterpictopnum#1#2#3#4{
\cleardoublepage
\twocolumn[{
\begin{@twocolumnfalse}
\includegraphics[width=#3\textwidth]{#2}
\chapter{#1}\label{#4}
\end{@twocolumnfalse}
}]
\squeezeup
}
\def\chapterpictopnonum#1#2#3#4{
\cleardoublepage
\twocolumn[{
\begin{@twocolumnfalse}
\includegraphics[width=#3\textwidth]{#2}
\chapter*{#1}\label{#4}
\end{@twocolumnfalse}
}]
\squeezeup
}
\def\chapterpicrightnum#1#2#3#4{
\cleardoublepage
\twocolumn[{
\moveup
\begin{@twocolumnfalse}
\begin{minipage}[t]{#3\textwidth}
\vspace{0pt}\raggedright
\chapter{#1}\label{#4}
\end{minipage}
\hspace{0.04\textwidth}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgap
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\end{@twocolumnfalse}
\movedown
}]
}
\def\chapterpicrightnonum#1#2#3#4{
\cleardoublepage
\twocolumn[{
\moveup
\begin{@twocolumnfalse}
\begin{minipage}[t]{#3\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}\label{#4}
\end{minipage}
\hspace{0.04\textwidth}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgap
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\end{@twocolumnfalse}
\movedown
}]
}
\def\chapterpicteasernum#1#2#3#4#5{
\cleardoublepage
\twocolumn[{
\moveup
\begin{@twocolumnfalse}
\begin{minipage}[t]{\textwidth}
\vspace{0pt}\raggedright
\chapter{#1}\label{#4}
\end{minipage}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgapsmall
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\hspace{0.04\textwidth}
\begin{minipage}[t]{#3\textwidth}
\picgapsmall
\LARGE
\raggedright
\textcolor{grey1}{\textbf{#5}}
\end{minipage}
\end{@twocolumnfalse}
\movedown
}]
}
\def\chapterpicteasernonum#1#2#3#4#5{
\cleardoublepage
\twocolumn[{
\moveup
\begin{@twocolumnfalse}
\begin{minipage}[t]{\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}\label{#4}
\end{minipage}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgapsmall
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\hspace{0.04\textwidth}
\begin{minipage}[t]{#3\textwidth}
\picgapsmall
\LARGE
\raggedright
\textcolor{grey1}{\textbf{#5}}
\end{minipage}
\end{@twocolumnfalse}
\movedown
}]
}
\def\gentitlepagenopic#1#2{
\fboxrule 0.0pt
\begin{titlepage}
\phantom{Die Titelseite}
\lefoot{\copyright \; Siemens AG \the\year. All rights reserved.}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageUpperLeft{%
\put(1.3cm,0cm){%
\makebox(0,0)[lt]{\includegraphics[width=4cm]{pics/cover/sie_logo_layer_petrol_rgb2.png}}%
}%
}%
}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageLowerLeft{%
\put(1.3cm,3cm){%
\makebox(0,0)[lt]{\includegraphics[width=3cm]{pics/cover/logo_multicore_expert-center_siemens.png}}%
}%
}%
}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-1.0cm}
\fcolorbox{black}{grey2}{
\begin{minipage}[c][1cm]{\paperwidth}
\hspace{0.8cm}
\fontsize{16}{20}\selectfont
\textcolor{white}{#1}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
% \vspace{-0.2cm}
\fcolorbox{black}{grey1}{
\begin{minipage}[c][4cm]{\paperwidth}
\textcolor{white}{}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
% \vspace{-0.2cm}
\hspace{0.8cm}
\begin{minipage}[c][4cm]{0.8\paperwidth}
\fontsize{36}{44}\selectfont
\textcolor{white}{#2}
\end{minipage}
\end{textblock}
\end{titlepage}
\ClearShipoutPicture
}
\def\gentitlepage#1#2#3{
\fboxrule 0.0pt
\begin{titlepage}
\phantom{Die Titelseite}
\lefoot{\copyright \; Siemens AG \the\year. All rights reserved.}
\AddToShipoutPictureBG{
\AtPageUpperLeft{\raisebox{-\height}
{\includegraphics[width=\paperwidth]{#1}}}
}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageUpperLeft{%
\put(1.3cm,0cm){%
\makebox(0,0)[lt]{\includegraphics[width=4cm]{pics/cover/sie_logo_layer_petrol_rgb.png}}%
}%
}%
}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageLowerLeft{%
\put(1.3cm,3cm){%
\makebox(0,0)[lt]{\includegraphics[width=3cm]{pics/cover/logo_multicore_expert-center_siemens.png}}%
}%
}%
}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-1.0cm}
\fcolorbox{black}{grey2}{
\begin{minipage}[c][1cm]{\paperwidth}
\hspace{0.8cm}
\fontsize{16}{20}\selectfont
\textcolor{white}{#2}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
% \vspace{-0.2cm}
\fcolorbox{black}{grey1}{
\begin{minipage}[c][4cm]{\paperwidth}
\textcolor{white}{}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
% \vspace{-0.2cm}
\hspace{0.8cm}
\begin{minipage}[c][4cm]{0.8\paperwidth}
\fontsize{36}{44}\selectfont
\textcolor{white}{#3}
\end{minipage}
\end{textblock}
\end{titlepage}
\ClearShipoutPicture
}
\def\genbackpage#1{
\pagebreak
\cleardoubleevenemptypage
\thispagestyle{empty}
\renewcommand{\baselinestretch}{1.1}\normalsize
\begin{textblock}{4}[0.0,0.0](0,0)
\fcolorbox{black}{grey1}{
\begin{minipage}[c][0.9\paperwidth]{\paperwidth}
\textcolor{white}{}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](0,0)
\vspace{0.44\paperheight}
\hspace{1.8cm}
\begin{minipage}[t][\paperwidth]{\paperwidth}
\textcolor{white}{#1}
\end{minipage}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](0,0)
\vspace{\paperwidth}
\vspace{-3.6cm}
\begin{minipage}[c][1cm]{\paperwidth}
\hspace{1.8cm}
\textcolor{black}{Printed in Germany\;|\;\copyright\;\copyrightdate \;Siemens AG}
\end{minipage}
\end{textblock}
}
\def\tableofcontentspic#1#2#3{
\cleardoublepage
\twocolumn[{
\moveup
\begin{@twocolumnfalse}
\begin{minipage}[t]{#3\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}
\end{minipage}
\hspace{0.04\textwidth}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgap
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\begin{minipage}[t]{0.2\textwidth}
\vspace{0pt}\raggedright
\hspace{15mm}
\end{minipage}
\begin{minipage}[t]{0.8\textwidth}
\phantomsection
\tableofcontents
\end{minipage}
\end{@twocolumnfalse}
\movedown
}]
}
\def\genlistoffigures#1{
\cleardoublepage
\onecolumn{
\chapter*{#1}
\vspace{1.5cm}
\begin{addmargin}[0.3\textwidth]{0cm}
\listoffigures
\end{addmargin}
}
}
\makeatother
% Copyright (C) nemadesign GbR
% $Rev: 56 $:
% $Date: 2014-09-02 21:55:06 +0200 (Di, 02. Sep 2014) $:
% definitions for single column style sheet
\usepackage{sty/siemens_core}
\usepackage{geometry}
\geometry
{
left=2.3cm, %linker Seitenrand
right=2.3cm, %rechter Seitenrand
top=25mm, %oben der Abstand
bottom=32mm %Unten der Abstand
}
% gap between columns
\setlength{\columnsep}{12mm}
% gap between paragraphs
\setlength{\parskip}{1ex}
\renewcommand\section{\@startsection
{section}{1}{0mm} % name, ebene, einzug
{1.3\baselineskip} % vor-abstand
{0.1\baselineskip} % nach-abstand
{\bfseries\sffamily\fontsize{13pt}{1.0}\color{orange}} % layout
}
\renewcommand\subsection{\@startsection
{subsection}{2}{0mm}
{0.8\baselineskip}
{0.1\baselineskip}
{\bfseries\sffamily\fontsize{13pt}{1.0}\color{grey1}}
}
\newcommand\sectionnonum{\@startsection
{section}{1}{0mm}
{1.3\baselineskip}
{0.1\baselineskip}
{\normalfont\fontsize{13pt}{1.0}\bfseries\color{orange}}*}
\newcommand\subsectionnonum{\@startsection
{subsection}{2}{0mm}
{0.8\baselineskip}
{0.01\baselineskip}
{\bfseries\sffamily\fontsize{13pt}{1.0}\color{grey1}}*}
% TOC without indents
% add space before TOC
\addtocontents{toc}{\protect\vspace{100pt}}
\renewcommand*{\@dotsep}{0.5}
\renewcommand*\l@chapter{\bfseries\bprot@dottedtocline{1}{0em}{3.0em}}
\renewcommand*\l@section{\mdseries\bprot@dottedtocline{2}{0em}{3.0em}}
\renewcommand*\l@subsection{\mdseries\bprot@dottedtocline{3}{0em}{3.0em}}
\renewcommand*\l@subsubsection{\mdseries\bprot@dottedtocline{4}{0em}{3.0em}}
\def\chapterpictopnum#1#2#3#4{
\cleardoublepage
\begin{minipage}[t]{\textwidth}
\picgap
\includegraphics[width=#3\textwidth]{#2}
\end{minipage}
\begin{minipage}[t]{\textwidth}
\vspace{0pt}\raggedright
\chapter{#1}\label{#4}
\end{minipage}
}
\def\chapterpictopnonum#1#2#3#4{
\cleardoublepage
\begin{minipage}[t]{\textwidth}
\picgap
\includegraphics[width=#3\textwidth]{#2}
\end{minipage}
\begin{minipage}[t]{\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}\label{#4}
\end{minipage}
}
\def\chapterpicrightnum#1#2#3#4{
\cleardoublepage
\begin{minipage}[t]{#3\textwidth}
\vspace{0pt}\raggedright
\chapter{#1}\label{#4}
\end{minipage}
\hspace{0.04\textwidth}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgap
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\vspace{2em}
}
\def\chapterpicrightnonum#1#2#3#4{
\cleardoublepage
\begin{minipage}[t]{#3\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}\label{#4}
\end{minipage}
\hspace{0.04\textwidth}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgap
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\vspace{2em}
}
\newcolumntype{a}[1]{>{\LARGE\raggedright\color{white}\columncolor{grey1}}p{#1}}
\newcolumntype{b}[1]{>{\columncolor{white}}p{#1}}
%\renewcommand*{\arraystretch}{0.0}
%\setlength{\arrayrulewidth}{0pt}
\arrayrulecolor{grey1}
\def\chapterpicteasernum#1#2#3#4#5{
\cleardoublepage
\setlength{\tabcolsep}{0mm}
\begin{minipage}[t]{\textwidth}
\vspace{0pt}\raggedright
\chapter{#1}\label{#4}
\end{minipage}
\begin{table}[ht]
\FPsub{\blah}{0.96}{#3}
\FPsub{\blub}{#3}{0.1}
\begin{tabular}[m]{b{\blah\textwidth} b{.05\textwidth} a{20pt} a{\blub\textwidth} a{19pt} }
\raisebox{-.92\totalheight}{\includegraphics[width=\blah\textwidth]{#2}} & & & #5 & \\
\end{tabular}
\end{table}
\setlength{\tabcolsep}{6pt}
}
\def\chapterpicteasernonum#1#2#3#4#5{
\cleardoublepage
\setlength{\tabcolsep}{0mm}
\begin{minipage}[t]{\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}\label{#4}
\end{minipage}
\begin{table}[ht]
\FPsub{\blah}{0.96}{#3}
\FPsub{\blub}{#3}{0.1}
\begin{tabular}[m]{b{\blah\textwidth} b{.05\textwidth} a{20pt} a{\blub\textwidth} a{19pt} }
\raisebox{-.92\totalheight}{\includegraphics[width=\blah\textwidth]{#2}} & & & #5 & \\
\end{tabular}
\end{table}
\setlength{\tabcolsep}{6pt}
}
\def\gentitlepagenopic#1#2{
\fboxrule 0.0pt
\begin{titlepage}
\phantom{Die Titelseite}
\lefoot{\copyright \; Siemens AG \the\year. All rights reserved.}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageUpperLeft{%
\put(1.3cm,0cm){%
\makebox(0,0)[lt]{\includegraphics[width=4cm]{pics/cover/sie_logo_layer_petrol_rgb2.png}}%
}%
}%
}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageLowerLeft{%
\put(1.3cm,3cm){%
\makebox(0,0)[lt]{\includegraphics[width=3cm]{pics/cover/logo_multicore_expert-center_siemens.png}}%
}%
}%
}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-1.2cm}
\fcolorbox{black}{grey2}{
\begin{minipage}[c][1cm]{\paperwidth}
\hspace{0.8cm}
\fontsize{16}{20}\selectfont
\textcolor{white}{#1}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-0.2cm}
\fcolorbox{black}{grey1}{
\begin{minipage}[c][4cm]{\paperwidth}
\textcolor{white}{}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-0.2cm}
\hspace{0.8cm}
\begin{minipage}[c][4cm]{0.8\paperwidth}
\fontsize{36}{44}\selectfont
\textcolor{white}{#2}
\end{minipage}
\end{textblock}
\end{titlepage}
\ClearShipoutPicture
}
\def\gentitlepage#1#2#3{
\fboxrule 0.0pt
\begin{titlepage}
\phantom{Die Titelseite}
\lefoot{\copyright \; Siemens AG \the\year. All rights reserved.}
\AddToShipoutPictureBG{
\AtPageUpperLeft{\raisebox{-\height}
{\includegraphics[width=\paperwidth]{#1}}}
}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageUpperLeft{%
\put(1.3cm,0cm){%
\makebox(0,0)[lt]{\includegraphics[width=4cm]{pics/cover/sie_logo_layer_petrol_rgb.png}}%
}%
}%
}
% Siemens Logo 4cm width, 1.5cm from left corner
\AddToShipoutPictureFG*{
\AtPageLowerLeft{%
\put(1.3cm,3cm){%
\makebox(0,0)[lt]{\includegraphics[width=3cm]{pics/cover/logo_multicore_expert-center_siemens.png}}%
}%
}%
}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-1.2cm}
\fcolorbox{black}{grey2}{
\begin{minipage}[c][1cm]{\paperwidth}
\hspace{0.8cm}
\fontsize{16}{20}\selectfont
\textcolor{white}{#2}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-0.2cm}
\fcolorbox{black}{grey1}{
\begin{minipage}[c][4cm]{\paperwidth}
\textcolor{white}{}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](1,0)
\vspace{\paperwidth}
\vspace{-0.2cm}
\hspace{0.8cm}
\begin{minipage}[c][4cm]{0.8\paperwidth}
\fontsize{36}{44}\selectfont
\textcolor{white}{#3}
\end{minipage}
\end{textblock}
\end{titlepage}
\ClearShipoutPicture
}
\def\genbackpage#1{
\pagebreak
\cleardoubleevenemptypage
\thispagestyle{empty}
\renewcommand{\baselinestretch}{1.1}\normalsize
\begin{textblock}{4}[0.0,0.0](0,0)
\fcolorbox{black}{grey1}{
\begin{minipage}[c][0.9\paperwidth]{\paperwidth}
\textcolor{white}{}
\end{minipage}
}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](0,0)
\vspace{0.38\paperheight}
\hspace{1.8cm}
\begin{minipage}[t][\paperwidth]{\paperwidth}
\textcolor{white}{#1}
\end{minipage}
\end{textblock}
\begin{textblock}{4}[0.0,0.0](0,0)
\vspace{\paperwidth}
\vspace{-4.0cm}
\begin{minipage}[c][1cm]{\paperwidth}
\hspace{1.8cm}
\textcolor{black}{Printed in Germany\;|\;\copyright\;\copyrightdate \;Siemens AG}
\end{minipage}
\end{textblock}
}
\def\tableofcontentspic#1#2#3{
\cleardoublepage
\onecolumn
\begin{minipage}[t]{\textwidth}
\begin{minipage}[t]{#3\textwidth}
\vspace{0pt}\raggedright
\chapter*{#1}
\end{minipage}
\hspace{0.04\textwidth}
\FPsub{\bla}{0.95}{#3}
\begin{minipage}[t]{\bla\textwidth}
\picgap
\includegraphics[width=\textwidth]{#2}
\end{minipage}
\end{minipage}
\tableofcontents
}
\def\genlistoffigures#1{
\cleardoublepage
\onecolumn{
\chapter*{#1}
\vspace{1.5cm}
\begin{addmargin}[0cm]{0cm}
\listoffigures
\end{addmargin}
}
}
% ----------------------------------------------------------------------
% Document class
% ----------------------------------------------------------------------
\documentclass[a4paper, 11pt, twoside, openright, footinclude, headinclude]{scrbook}
% ----------------------------------------------------------------------
% Packages
% ----------------------------------------------------------------------
\usepackage{sty/siemens_single}
\usepackage{amsmath}
\usepackage{listing}
\usepackage{array} % for tabular
\usepackage{pifont} % for \myCheck, \myCross
\usepackage[hyphens]{url}
\usepackage[hidelinks]{hyperref} % hyperref without colored links
\usepackage{draftwatermark}
\usepackage{xspace}
\usepackage{pgf}
\usepackage{tikz}
% ----------------------------------------------------------------------
% TikZ
% ----------------------------------------------------------------------
\usetikzlibrary{arrows}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{matrix}
\usetikzlibrary{patterns}
\usetikzlibrary{positioning}
% ----------------------------------------------------------------------
% Document specific macros and settings
% ----------------------------------------------------------------------
\def\lstwidth{0.8\columnwidth}
\def\embb{EMB$^\mathsf{2}$\xspace}
\SetWatermarkColor[gray]{0.95}
\newcommand{\leadingzero}[1]{\ifnum #1<10 0\the#1\else\the#1\fi}
\newcommand{\monthword}[1]{\ifcase#1\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi}
% ----------------------------------------------------------------------
% Dataflow process networks
% ----------------------------------------------------------------------
\newlength{\dpnunit}
\setlength{\dpnunit}{5mm}
\tikzstyle{nodestyle}=[draw, semithick, minimum size=\dpnunit, anchor=center, minimum height=2\dpnunit]
\tikzstyle{edgestyle}=[draw, thick, ->, >=stealth']
\tikzstyle{function}=[rectangle, nodestyle, inner sep=2pt, minimum width=2\dpnunit, minimum height=1.5\dpnunit]
\tikzstyle{invisible}=[anchor=center]
\tikzstyle{selector}=[trapezium, nodestyle, trapezium angle=-70, trapezium stretches=true, minimum width=2\dpnunit, minimum height=\dpnunit]
\tikzstyle{switch}=[trapezium, nodestyle, trapezium angle=70, trapezium stretches=true, minimum width=2\dpnunit, minimum height=\dpnunit]
\tikzstyle{junction}=[circle, draw, fill, inner sep=0pt, minimum size=1mm, anchor=center]
\newcommand{\dpninv}[1]{\node [invisible, inner sep=2pt, minimum size=0pt] (#1) {};}
\newcommand{\dpnsrc}[2]{\node [function] (#1) {#2};}
\newcommand{\dpnsnk}[2]{\node [function] (#1) {#2};}
\newcommand{\dpnser}[2]{\node [function] (#1) {#2};}
\newcommand{\dpnpar}[2]{\node [function, double] (#1) {#2};}
\newcommand{\dpnsel}[1]{\node [selector] (#1) {}; \draw (#1.north west) [yshift=-4.5pt] node {\ttrue}; \draw (#1.north east) [yshift=-4.5pt] node {\tfalse};}
\newcommand{\dpnswi}[1]{\node [switch] (#1) {}; \draw (#1.south west) [yshift=4.5pt] node {\ttrue}; \draw (#1.south east) [yshift=4.5pt] node {\tfalse};}
\newcommand{\dpnjun}[1]{\node [junction] (#1) {};}
% ----------------------------------------------------------------------
\begin{document}
% ----------------------------------------------------------------------
\input{customize} % To get template specific stuff
% Set title and author
% short title is used on the front cover and on each page header
\renewcommand{\shorttitle}{\embb Introduction and Tutorial}
% short date is printed on each page header, right next to short title
\renewcommand{\shortdate}{\monthword{\month} \the\year}
% copyright date is printed on the back cover
\renewcommand{\copyrightdate}{\leadingzero{\month}.\the\year}
% 1st paramter: a square(!) picture
% 2nd parameter: short tile (one line)
% 3rd parameter: long title (up to two lines)
\gentitlepage{pics/chicago-square.jpg}{\LARGE Siemens Corporate Technology | \monthword{\month} 2016}{\scalebox{0.9}{Embedded Multicore Building Blocks}\\\scalebox{0.9}{Introduction and Tutorial}}
% List the authors and contributors on the second page, right after the cover page
% 1st parameter: contributors (optional)
% 2nd parameter: author(s)
\printAuthors{
Bernhard Gatzhammer, bernhard.gatzhammer@siemens.com \newline
Christian Kern, christian.kern@siemens.com \newline
Tobias Sch\"ule, tobias.schuele@siemens.com \newline
Marcus Winter, marcus.winter.ext@siemens.com \newline
\newline
Siemens AG \newline
Corporate Technology \newline
Research \& Technology Center \newline
CT RTC ITP SES-DE \newline
Otto-Hahn-Ring 6 \newline
81739 M\"unchen \newline
Germany
}
% This is from the template:
% \tableofcontentspic{Contents}{pics/chapter/Fotolia_43587256_X.jpg}{\chapterpicwidth}
% And this is our custom toc
\chapter*{Contents}
\tableofcontents
% ----------------------------------------------------------------------
% Content
% ----------------------------------------------------------------------
% \input{content/preface}
\input{content/introduction}
\input{content/mtapi}
\input{content/tasks}
\input{content/algorithms}
\input{content/dataflow}
\input{content/containers}
% ----------------------------------------------------------------------
% References
% ----------------------------------------------------------------------
% the following two macros fix the problem of the incorrect ToC pointer to the bibliography.
\cleardoublepage
\phantomsection
\addcontentsline{toc}{chapter}{Bibliography}
\bibliographystyle{IEEEtran}
% balance the columns at the last page of the bibliography
\balance
\bibliography{references}
% ----------------------------------------------------------------------
% Back Cover
% ----------------------------------------------------------------------
\backcover
\end{document}
File added
create_tarball.sh diff
#!/usr/bin/env bash
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#function for printing usage
usage() {
echo "Create a tarball of the project. Specify the project root with the";
echo "-d parameter. Optionally, specify the -v switch to get verbose output";
echo "and/or the -q switch, for non-interactive (without user inputs)";
echo "processing.";
echo "";
echo "Version number and project name is automatically derived from CMakeLists.txt";
echo "in the project's root.";
echo "Tarball name: [PROJECT_NAME]_[VERSION_NUMBER].tar.gz";
echo "Example call (from the scripts directory as working directory):";
echo "$0 -d ../";
echo "";
echo "Usage: $0 [-d <root project dir>] [-v] [-q]" 1>&2; exit 1;
}
#check if all dependencies are fulfilled
for DEPENDENCY in rsync pdflatex bibtex cp tar mktemp cd grep cmake find file echo python realpath sed
do
command -v $DEPENDENCY >/dev/null 2>&1 || { echo >&2 "This script requires $DEPENDENCY but it's not installed. Exiting."; exit 1; }
done
#get command line options
while getopts "d:vq" o; do
case "${o}" in
d)
d=${OPTARG}
;;
v)
v=1
;;
q)
q=1
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
#used as wrapper, for switching between verbose and normal mode
redirect_cmd() {
if [ -z "${v}" ]; then
"$@" > /dev/null 2>&1
else
"$@"
fi
}
#user has to specify directory
if [ -z "${d}" ]; then
usage
fi
#the specified directory has to exist
if [ ! -d "$d" ]; then
echo "--> ! Error, directory $d does not exist or is not a directory!"
echo ""
usage
fi
CMAKEFILE="$d/CMakeLists.txt"
if [ ! -f "$CMAKEFILE" ]; then
echo "--> ! Error, could no locate CMakeLists.txt"
echo ""
usage
fi
#derive version number from cmake script
VERSION_MAJOR=`cat $CMAKEFILE | grep EMBB_BASE_VERSION_MAJOR | sed "s/^[^0-9]*\([0-9]\+\)[^0-9]*$/\1/g"`
VERSION_MINOR=`cat $CMAKEFILE | grep EMBB_BASE_VERSION_MINOR | sed "s/^[^0-9]*\([0-9]\+\)[^0-9]*$/\1/g"`
VERSION_PATCH=`cat $CMAKEFILE | grep EMBB_BASE_VERSION_PATCH | sed "s/^[^0-9]*\([0-9]\+\)[^0-9]*$/\1/g"`
VERSION_NUMBER="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"
#generate tarball name
PROJECT_NAME=`cat $CMAKEFILE | grep project.*\(.*\) | sed "s/^[^(]*(\([^)]*\)).*$/\1/g" | tr '[:upper:]' '[:lower:]'`
n="${PROJECT_NAME}-${VERSION_NUMBER}"
TARBALL_NAME="${n}.tar.gz"
#verify that tarball doesn't allow forbidden characters
if ! [[ $TARBALL_NAME =~ ^[a-zA-Z0-9|\.|\_|-]+$ ]]; then
echo "--> Want to create tarball with name $TARBALL_NAME." >&2
echo '--> ! Filename not valid, only a-z, A-Z, .,- and _ characters are allowed' >&2 # write to stderr
exit 1
fi
if [ -z "${q}" ]; then
#in interactive mode, ask the user if the tarball shall be created with this filename
echo "--> Do you wish to create a tarball with the name $TARBALL_NAME in the current directory?"
select yn in "Yes" "No"; do
case $yn in
Yes ) break;;
No ) echo Leaving tarball creation; exit 1;;
esac
done
else
echo "--> Tarball with name $TARBALL_NAME will be created."
fi
#check if file with the tarball_name already exists. In interactive mode, ask the user if this file shall be deleted. Otherwise just exit.
if [ -f "$TARBALL_NAME" ]; then
if [ -z "${q}" ]; then
echo "--> File $TARBALL_NAME exists. Delete file?"
select yn in "Yes" "No"; do
case $yn in
Yes ) break;;
No ) echo Leaving tarball creation; exit 1;;
esac
done
rm $TARBALL_NAME
if [ -f "$TARBALL_NAME" ]; then
echo "Could not delete $TARBALL_NAME"
exit 1
fi
else
echo "--> ! File $TARBALL_NAME exists. Delete first. Exiting."
exit 1;
fi
fi
#temporary directory for doxygen
MYTMPDIR_DOXY_BUILD=`mktemp -d`
#temporary directory for building other things (e.g. Latex or integrating snippets into examples)
MYTMPDIR_BUILD=`mktemp -d`
#temporary target directory, from this the tarball will be created
MYTMPDIR=`mktemp -d`
echo "--> Creating temporary directories $MYTMPDIR $MYTMPDIR_BUILD $MYTMPDIR_DOXY_BUILD"
#install traps, deleting the temporary directories when exiting
function finish {
rm -rf $MYTMPDIR
rm -rf $MYTMPDIR_DOXY_BUILD
rm -rf $MYTMPDIR_BUILD
}
trap finish EXIT
PROJECT_DIR_FULLPATH=`realpath ${d}`
echo "--> Generating Doxygen"
REMEMBER_CUR_DIR=$(pwd)
cd "$MYTMPDIR_DOXY_BUILD"
echo "---> Initialize CMake"
redirect_cmd cmake "$PROJECT_DIR_FULLPATH"
echo "---> Call CMake with target Doxygen"
redirect_cmd cmake --build . --target doxygen
REFMAN_TEXFILE="$MYTMPDIR_DOXY_BUILD/latex/refman.tex"
DO_CREATE_LATEXDOC=true
if [ ! -f "$REFMAN_TEXFILE" ]; then
echo "---> ! Could not find doxygen tex source $REFMAN_TEXFILE. Leaving tarball creation."
exit 1;
fi
#to resolve all references, pdf and bibtex have to be run more than once. With 4 runs, we should get everything right.
PDFRUNS=4
echo "---> Build Doxygen PDF reference"
if [ "$DO_CREATE_LATEXDOC" = true ] ; then
cd "$MYTMPDIR_DOXY_BUILD/latex"
for ((i=1; i<=$PDFRUNS; i++)); do
echo "----> LaTeX Run ($i/$PDFRUNS)"
redirect_cmd pdflatex refman.tex
redirect_cmd bibtex refman
done
fi
cd "$REMEMBER_CUR_DIR"
echo "--> Calling rsync to temporary folder 1/2 ($MYTMPDIR)"
#this is the rsync, to the folder from which the tarball will be created later. Exclude everything, that should not be in the tarball. Also exclude things, that are generated somewhere else, like examples.
redirect_cmd rsync \
--exclude ".git" \
--exclude ".gitignore" \
--exclude ".gitattributes" \
--exclude "build*/" \
--exclude "scripts/*.tar.gz" \
--exclude "scripts/cpplint.py" \
--exclude "scripts/create_tarball.sh" \
--exclude "scripts/insert_license.sh" \
--exclude "scripts/license.*" \
--exclude "scripts/license_*" \
--exclude "scripts/remove_license.sh" \
--exclude "mtapi/MTAPI.mm" \
--exclude ".cproject" \
--exclude ".gitattributes" \
--exclude ".project" \
--exclude "*.blg" \
--exclude "*.fls" \
--exclude "*.bbl" \
--exclude "*.fdb_latexmk" \
--exclude "*.log" \
--exclude "*.out" \
--exclude "*.toc" \
--exclude "*.aux" \
--exclude "doc/tutorial/sty" \
--exclude "doc/tutorial/pics" \
--exclude "doc/tutorial/content" \
--exclude "doc/tutorial/*.tex" \
--exclude "doc/tutorial/*.bib" \
--exclude "doc/reference/*.xml" \
--exclude "doc/reference/*.dox" \
--exclude "doc/reference/*.in" \
--exclude "doc/reference/header.html" \
--exclude "doc/reference/*.css" \
--exclude "doc/examples" \
--exclude "doc/examples/insert_snippets.py" \
--exclude ".travis.yml" \
--archive --recursive ${d} $MYTMPDIR/${n}
echo "--> Replace version number in README"
README_FILE="$MYTMPDIR/${n}/README.md"
#replace version number in readme
if [ -f $README_FILE ]; then
sed -i "s/\[VERSION_NUMBER_TEMPLATE\]/$VERSION_NUMBER/g" $README_FILE
fi
echo "--> Calling rsync to temporary folder 2/2 ($MYTMPDIR_BUILD)"
#doing a rsync to another temporary folder, which will be used to build things, like e.g. the tutorial pdf.
redirect_cmd rsync \
--archive --recursive ${d} $MYTMPDIR_BUILD
echo "--> Generating Tutorial PDF"
TUTORIAL_TEX_DIR="$MYTMPDIR_BUILD/doc/tutorial"
REMEMBER_CUR_DIR=$(pwd)
TUTORIAL_PDF_SOURCE="$TUTORIAL_TEX_DIR/tutorial.pdf"
TUTORIAL_PDF_TARGET="$MYTMPDIR/${n}/doc/tutorial/tutorial.pdf"
if [ -f "$TUTORIAL_TEX_DIR/tutorial.tex" ]; then
cd "$TUTORIAL_TEX_DIR"
for ((i=1; i<=$PDFRUNS; i++)); do
echo "---> LaTeX Run ($i/$PDFRUNS)"
redirect_cmd pdflatex tutorial.tex
redirect_cmd bibtex tutorial
done
if [ -f "$TUTORIAL_PDF_SOURCE" ]; then
cp $TUTORIAL_PDF_SOURCE $TUTORIAL_PDF_TARGET
fi
fi
cd "$REMEMBER_CUR_DIR"
REFMAN_TARGET="$MYTMPDIR/${n}/doc/reference/reference.pdf"
REFMAN_SOURCE="$MYTMPDIR_DOXY_BUILD/latex/refman.pdf"
echo "--> Integrating Example Snippets"
REMEMBER_CUR_DIR=$(pwd)
EXAMPLES_DIR="$MYTMPDIR_BUILD/doc/examples"
INTEGRATE_SNIPPETS_SCRIPT="insert_snippets.py"
EXAMPLES_TARGET_DIR="$MYTMPDIR/${n}/doc/"
if [ -f $EXAMPLES_DIR/$INTEGRATE_SNIPPETS_SCRIPT ]; then
cd "$EXAMPLES_DIR"
echo "---> Calling integrate script"
redirect_cmd python insert_snippets.py
if [ -d $EXAMPLES_TARGET_DIR ]; then
echo "---> Copy integrated examples back"
#The examples have been integrated. Copy the integrated source files.
redirect_cmd rsync --archive --recursive $EXAMPLES_DIR $EXAMPLES_TARGET_DIR \
--exclude=*snippet.h \
--exclude=*fragmented.h \
--exclude=*snippet.cc \
--exclude=*fragmented.cc \
--exclude=*$INTEGRATE_SNIPPETS_SCRIPT
fi
fi
cd "$REMEMBER_CUR_DIR"
echo "--> Copy reference manual"
if [ -f $REFMAN_SOURCE ]; then
cp $REFMAN_SOURCE $REFMAN_TARGET
else
echo "--> ! Could not find doxygen pdf document $REFMAN_SOURCE. Exiting"
exit 1;
fi
if [ -d $MYTMPDIR_DOXY_BUILD/html ]; then
redirect_cmd rsync --archive --recursive $MYTMPDIR_DOXY_BUILD/html/ $MYTMPDIR/${n}/doc/reference/doxygen_html_generated
else
echo "Doxygen HTML was not generated. Tarball will not contain HTML reference documentation. Exiting."
exit 1;
fi
echo "--> Checking line endings"
#check for files, that have windows file endings. Those are forbidden.
WINLINES=`find $MYTMPDIR/${n} -not -type d -exec file "{}" ";" | grep CRLF`
if [ -n "$WINLINES" ]; then
echo "Detected Dos line endings in following files:"
echo "$WINLINES"
echo "Error: The project guidelines forbid Dos line endings. Exiting."
exit 1;
fi
#sanity check... verify, that expected targets are there, otherwise abort...
if ! [ -f $MYTMPDIR/${n}/doc/examples/main.cc ]; then
echo "--> ! Examples missing. Exiting."
exit 1;
fi
if ! [ -f $MYTMPDIR/${n}/doc/tutorial/tutorial.pdf ]; then
echo "--> ! Tutorial PDF missing. Exiting."
exit 1;
fi
if ! [ -f $MYTMPDIR/${n}/doc/reference/reference.pdf ]; then
echo "--> ! Reference PDF documentation missing. Exiting."
exit 1;
fi
if ! [ -f $MYTMPDIR/${n}/doc/reference/doxygen_html_generated/index.html ]; then
echo "--> ! Reference HTML documentation missing. Exiting."
exit 1;
fi
#finally, build the tarball.
echo "--> Calling tar"
tar -czf $TARBALL_NAME -C $MYTMPDIR ${n}
echo "--> Done. Created $TARBALL_NAME."
#!/usr/bin/env bash
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
usage() {
echo "Specify license file to add to each source file";
echo "and directory where to start to find files.";
echo "Example call:";
echo "./insert_license.sh -d ../ -l license.txt";
echo "";
echo "Usage: $0 [-d directory] [-l license_file]" 1>&2; exit 1;
}
while getopts ":d:l:" o; do
case "${o}" in
d)
d=${OPTARG}
;;
l)
l=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${d}" ] || [ -z "${l}" ]; then
usage
fi
if [ ! -d "$d" ]; then
echo "Error, directory $d does not exist or is not a directory!"
echo ""
usage
fi
if [ ! -f "$l" ]; then
echo "Error, license file $l does not exist or is not a file!"
echo ""
usage
fi
for FILE in `find ${d} -name "*.h" -o -name "*.cc" -o -name "*.c" -o -name "*.h.in" -type f`
do
if ! grep -q COPYRIGHT $FILE
then
echo "Inserting license to: $FILE"
cat ${l} $FILE > $FILE.new && mv $FILE.new $FILE
fi
done
/*
* Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#!/usr/bin/env bash
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
usage() {
echo "Specify license file to remove from each source file";
echo "and directory where to start to find files.";
echo "License is only removed if existing.";
echo "";
echo "Example call:";
echo "./remove_license.sh -d ../ -l license.txt";
echo "";
echo "Usage: $0 [-d directory] [-l license_file]" 1>&2; exit 1;
}
while getopts ":d:l:" o; do
case "${o}" in
d)
d=${OPTARG}
;;
l)
l=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${d}" ] || [ -z "${l}" ]; then
usage
fi
if [ ! -d "$d" ]; then
echo "Error, directory $d does not exist or is not a directory!"
echo ""
usage
fi
if [ ! -f "$l" ]; then
echo "Error, license file $l does not exist or is not a file!"
echo ""
usage
fi
LINES=`cat ${l} | wc -l`
LINESP1=$(($LINES + 1))
for FILE in `find ${d} -name "*.h" -o -name "*.cc" -o -name "*.c" -o -name "*.h.in" -type f`
do
if grep -q COPYRIGHT $FILE
then
echo "Processing: $FILE"
TEMP=$(mktemp /tmp/temporary-file.XXXXXXXX)
head -n $LINES $FILE > ${TEMP}
if [[ ! `diff ${TEMP} ${l}` ]]; then
echo "Strip license from file: $FILE"
tail -n +$LINESP1 $FILE > ${FILE}.new && mv ${FILE}.new ${FILE}
fi
fi
done
#!/usr/bin/env bash
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
usage() {
echo "Run Google C++ Style Guide checking on project.";
echo "Specify EMBB root directory with -d and the";
echo "cpplint executable with -c. If not specified";
echo "it is assumed the cpplint binary is contained";
echo "in the current working directory.";
echo "";
echo "Usage: $0 [-d directory] [-c cpplint_executable] " 1>&2; exit 1;
}
while getopts ":d:c:" o; do
case "${o}" in
d)
d=${OPTARG}
;;
c)
c=${OPTARG}
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z "${d}" ]; then
usage
fi
if [ ! -d "$d" ]; then
echo "Error: directory $d does not exist or is not a directory!"
echo ""
usage
fi
if [ -z "${c}" ]; then
echo "cpplint binary not specified, assuming to be contained in the current working directory!"
c="./cpplint.py"
fi
if [ ! -f "${c}" ]; then
echo "Error: cannot find cpplint script (Location: ${c})"
echo
usage
fi
##Excluded Rules
EXCLUDED_RULES="-runtime/references,-runtime/int,-build/include_order,-readability/multiline_comment,-readability/streams,-readability/alt_tokens,-whitespace/comments"
PARENTHESIS_RULE=",-whitespace/parens"
C_CAST_RULE=",-readability/casting"
LONG_LINES_RULE=",-whitespace/line_length"
retval=0
##Excluded files
RAND_FILES=( embb_mtapi_test_group.cc embb_mtapi_test_queue.cc embb_mtapi_test_task.cc queue_test-inl.h )
for project in base_c mtapi_c mtapi_plugins_c/mtapi_network_c mtapi_plugins_c/mtapi_opencl_c base_cpp mtapi_cpp tasks_cpp algorithms_cpp containers_cpp dataflow_cpp
do
echo "-> Doing project: $project"
dir=$d/$project
if [ ! -d "$dir" ]; then
echo "Error: cannot find directory $dir for project $project"
echo
usage
fi
for file in `find $dir \( -name "*.cc" -o -name "*.h" -o -name "*inl.h" -o -name "*.c" \) -and -not -path "*/src/CL/*"`
do
echo "--> Run cpplint on file $file"
current_rules=$EXCLUDED_RULES
if [[ $file =~ \.h$ ]]; then
current_rules+=$PARENTHESIS_RULE
fi
if [[ $file =~ \.c$ ]] || [[ $file =~ \mtapi.h$ ]]; then
current_rules+=$C_CAST_RULE
fi
if [[ $file == *atomic* ]]; then
current_rules+=$LONG_LINES_RULE
fi
############
#Per file exclusion rules
if [[ $file == *generate_atomic_implementation_template.h ]]; then
current_rules+=",-build/header_guard" # This file needs to be included multiple times
fi
if [[ $file == *atomic.h ]]; then
current_rules+=",-whitespace/indent" # indention is misinterpreted for this file
fi
if [[ $file == *atomic_arithmetic.h ]]; then
current_rules+=",-readability/function" # All parameters should be named in a function
fi
if [[ $file == *object_pool-inl.h ]]; then
current_rules+=",-readability/function" # All parameters should be named in a function (triggers error with clang if named...)
fi
for filename in "${RAND_FILES[@]}"; do
if [[ $file =~ $filename ]]; then
current_rules+=",-runtime/threadsafe_fn" # These tests are allowed to use the thread unsafe rand()
fi
done
python ${c} --filter=$current_rules --root="$project/include" --output=vs7 $file
if [[ ! $? -eq 0 ]]; then
retval=$((retval+1))
fi
done
done
echo "$retval files contained errors."
exit $retval
#!/bin/sh
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Needs to be located in the folder containing the tests!!
# Is copied automatically there when generating build files with cmake.
EMBB_TEST_EXECUTABLES="@EXPECTED_EMBB_TEST_EXECUTABLES@"
SCRIPT_LOCATION="$0"
# case we have symlinks...
while [ -h "$SCRIPT_LOCATION" ] ; do
SCRIPT_LOCATION=`readlink "$SCRIPT_LOCATION"`
done
DIR=`dirname "$SCRIPT_LOCATION"`
for TEST in $(echo $EMBB_TEST_EXECUTABLES | tr ";" " "); do
"$DIR/$TEST".exe;
done
#!/bin/sh
# Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# Needs to be located in the folder containing the tests!!
# Is copied automatically there when generating build files with cmake.
EMBB_TEST_EXECUTABLES="@EXPECTED_EMBB_TEST_EXECUTABLES@"
SCRIPT_LOCATION="$0"
# case we have symlinks...
while [ -h "$SCRIPT_LOCATION" ] ; do
SCRIPT_LOCATION=`readlink "$SCRIPT_LOCATION"`
done
DIR=`dirname "$SCRIPT_LOCATION"`
for TEST in $(echo $EMBB_TEST_EXECUTABLES | tr ";" " "); do
$DIR/$TEST;
done
:: Copyright (c) 2014-2016, Siemens AG. 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. Redistributions in binary form must reproduce the above copyright notice,
:: this list of conditions and the following disclaimer in the documentation
:: and/or other materials provided with the distribution.
::
:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
:: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
:: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
:: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
:: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
:: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
:: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
:: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
:: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
:: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
:: POSSIBILITY OF SUCH DAMAGE.
:: Needs to be located in the folder containing the tests!!
:: Is copied automatically there when generating build files with cmake.
@echo off
setlocal EnableDelayedExpansion
SET NUM_ERRORS=0
SET DIR=%~dp0
SET EMBB_EXECUTABLES=@EXPECTED_EMBB_TEST_EXECUTABLES@
call :parse "%EMBB_EXECUTABLES%"
goto :end
:parse
set list=%1
set list=%list:"=%
FOR /f "tokens=1* delims=;" %%a IN ("%list%") DO (
if not "%%a" == "" call :sub %%a
if not "%%b" == "" call :parse "%%b"
)
exit /b
:sub
call "%DIR:~0,-1%\%1.exe"
if not !ERRORLEVEL! ==0 set /a NUM_ERRORS=!NUM_ERRORS!+1
exit /b
:end
if not !NUM_ERRORS! ==0 (
echo.
SET ERRORLEVEL=1
echo "Number of failed tests: !NUM_ERRORS!"
exit /b !NUM_ERRORS!
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment