The Synch framework consists of 3 main parts, i.e. the Runtime/Primitives, the library of concurrent data-structures and the benchmarks (see the figure below) . The Runtime/Primitives part provides some basic functionality for creating and managing threads, functionality for basic atomic primitives (e.g. Compare&Swap, Fetch&Add, fences, simple synchronization barriers, etc.), mechanisms for basic memory allocation/management (e.g. memory pools, etc.), functionality for measuring time, reporting CPU counters, etc. Furthermore, the Runtime/Primitives provides a simple and lightweight library of user level-threads that can be used in order to evaluate the provided data-structures and algorithms.
The Concurrent library utilizes the building blocks of the Runtime/Primitives layer in order to provide all the concurrent data-structures (e.g. combining objects, queues, stacks, etc.). For almost every concurrent data-structure or synchronization mechanism, Synch provides at least one benchmark for evaluating its performance.
Before contributing to this repository, you are encouraged to first discuss the issue, change or contribution that you wish to make. In order to do this, please open an issue or send an email. We are open to discuss new ideas, improvements or any other contributions. Please note that we have a Code of conduct that should be considered in all your interactions with the project.
- Fork the repository.
- Create a new branch for your patch.
- Make your updates/changes.
- Open a pull request.
- Submit your pull request targeting the current development branch (i.e. the branch with the highest version number).
- Get it reviewed.
Before committing a new patch, follow the steps below for checking the coding style of your patch.
- Ensure that you have installed
clang-format
package (version >= 9). - After cloning the repository you need to run
git config --local core.hooksPath .git_hooks
to enable recommended code style checks (placed in.clang_format
file) during git commit. If the tool discovers inconsistencies, it will create a patch file. Please follow the instructions to apply the patch before opening a pull request.
In general, please conform your coding styling to the following conventions:
- ident style:
- Please avoid using tabs, use spaces instead of tabs.
- comments:
- Comments start with
//
. - For exposing documentation to Doxygen start comments with
///
.
- Comments start with
- structs:
- Self-explanatory names: a struct
DoubleEndedQueueStruct
will tell the developer what the struct is used for. - Use a capital-letter for the first character of the struct.
- Please use
typedef
for simplifying struct-naming, e.g.DoubleEndedQueueStruct
instead ofstruct DoubleEndedQueueStruct
. - All the public structs provided by the runtime/primitives to the end-user should start with the
Synch
prefix (starting from v.3.0.0), e.g.SynchMemoryStruct
, etc.
- Self-explanatory names: a struct
- functions: for functions the following rules hold:
- Self-explanatory names: a function
getMemory()
will tell the developer what it returns as well asgetThreadId()
, etc. - Avoid using a capital-letter for the first character of the function.
- All the public functions provided by the runtime/primitives to the end-user should start with the
synch
prefix (starting from v.3.0.0), i.e.synchGetMemory
. - All the internal functions should NOT start with the
synch
prefix, i.e.getMemory
.
- Self-explanatory names: a function
- definitions:
- Use capital letters for all the definitions.
- It is strongly recommended all the public definitions to start with the
SYNCH_
prefix.
- memory allocation and alignment:
- For memory management, please do not use
malloc
,calloc
, etc. functions directly. - Please use the memory management functionality provided by
primitives.h
. - In case that the functionality of
primitives.h
does not meet the needs of your patch, please consider to expand it.
- For memory management, please do not use
- atomic primitives and other processor primitives:
- Do not use
asm
assembly code or compiler intrinsics directly in your code. - Please use the primitives provided by
primitives.h
. - In case that the functionality of
primitives.h
does not meet the needs of your patch, please consider to expand it.
- Do not use
- file-naming conventions:
- The source-code of each concurrent data-structure that is provided is placed under the
libconcurrent/concurrent
directory. - Each concurrent data-structure provides a public API that is a
.h
header-file placed under thelibconcurrent/includes
directory. - For each concurrent data-structure, at least one benchmark is provided under the
benchmarks
directory. - All benchmarks are placed under the benchmarks directory. The source-code of each of them has the
bench.c
suffix, while the prefix is the name of the concurrent data-structure that is benchmarked (i.e. thebenchmarks/ccsynchbench.c
file is a benchmark for the CC-Synch combining object).
- The source-code of each concurrent data-structure that is provided is placed under the
- It is strongly recommended to sufficiently comment your code.
- At least, ensure that all the public functionality of your patch provides adequate documentation through Doxygen.
Whenever the DEBUG
macro is defined in libconcurrent/config.h
, most of the provided benchmarks make some basic sanity-checks in order to ensure that the provided concurrent data-structures behave appropriately. For example, in concurrent stack benchmarks where each thread executes a specific amount of Push/Pop pairs of operations on a concurrent stack, the DEBUG
macro ensures that after the end of the benchmark the stack is empty of elements (given that the amount of elements in the initialization phase of the benchmark is zero).
The validate.sh
script compiles the sources in DEBUG
mode and runs a big set of benchmarks with various numbers of threads. After running each of the benchmarks, the script evaluates the DEBUG
output and in case of success it prints PASS
. In case of a failure, the script simply prints FAIL
.
In case that you want to contribute a new concurrent data-structure, you should provide sanity-check code in a benchmark that should be activated whenever DEBUG
macro is defined. Please, don't forget to update the validate.sh
script appropriately.
- Update the README.md with details.
- Log your contribution/changes to the CHANGELOG.md file.
- Increase the version numbers (if needed) in any example-files and the README.md to the new version that this pull Request would represent. The versioning scheme that we use (for releases later than v2.2.0) is SemVer. In short, given a version number MAJOR.MINOR.PATCH, increment the:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards compatible manner, and
- PATCH version when you make backwards compatible bug fixes.