Skip to content

Commit

Permalink
Version 0.1.7 (#141)
Browse files Browse the repository at this point in the history
Co-authored-by: friendlyanon <[email protected]>
Co-authored-by: friendlyanon <[email protected]>
Co-authored-by: NN <[email protected]>
Co-authored-by: NN <[email protected]>
Co-authored-by: Zakhar Karlin <[email protected]>
Co-authored-by: chausner <[email protected]>
Co-authored-by: autoantwort <[email protected]>
Co-authored-by: chausner <[email protected]>
Co-authored-by: R. Andrew Ohana <[email protected]>
Co-authored-by: Mathias Eggert <[email protected]>
Co-authored-by: Mathias Eggert <[email protected]>
Co-authored-by: Nick <[email protected]>
Co-authored-by: gotnone <[email protected]>
Co-authored-by: Stanley Pinchak <[email protected]>
  • Loading branch information
15 people authored Jul 15, 2023
1 parent 944a65f commit 7a88f54
Show file tree
Hide file tree
Showing 51 changed files with 1,014 additions and 843 deletions.
3 changes: 0 additions & 3 deletions .github/actions/fetch-clang/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ runs:
if (${version} -eq 12) {
$pkgs += "libunwind-${version}-dev"
}
if (${version} -ge 14) {
$pkgs += "libclang-rt-${version}-dev"
}
Invoke-NativeCommand sudo apt-get install -y $pkgs
Add-Content "${env:GITHUB_OUTPUT}" "clang=$((Get-Command clang-${version}).Source)"
Add-Content "${env:GITHUB_OUTPUT}" "clangxx=$((Get-Command clang++-${version}).Source)"
Expand Down
46 changes: 46 additions & 0 deletions .github/actions/fetch-gcc/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Fetch GCC
description: Puts gcc's path into the output

inputs:
version:
description: Version of GCC to fetch
required: true
outputs:
gcc:
description: Path of gcc executable
value: ${{ steps.script.outputs.gcc }}
gplusplus:
description: Path of g++ executable
value: ${{ steps.script.outputs.gplusplus }}

runs:
using: composite
steps:
- id: script
shell: pwsh
run: |
$version = "${{ inputs.version }}"
function Invoke-NativeCommand {
$command = $args[0]
$arguments = $args[1..($args.Length)]
& $command @arguments
if ($LastExitCode -ne 0) {
Write-Error "Exit code $LastExitCode while running $command $arguments"
}
}
if ($IsMacOs) {
Invoke-NativeCommand brew install gcc@${version}
Add-Content "${env:GITHUB_OUTPUT}" "gcc=gcc-${version}"
Add-Content "${env:GITHUB_OUTPUT}" "gplusplus=g++-${version}"
} elseif ($IsLinux) {
# install Homebrew
$env:CI = "1"
Invoke-NativeCommand /bin/bash -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)
$env:CI = $null
# install gcc
Invoke-NativeCommand /home/linuxbrew/.linuxbrew/bin/brew install gcc@${version}
Add-Content "${env:GITHUB_OUTPUT}" "gcc=/home/linuxbrew/.linuxbrew/bin/gcc-${version}"
Add-Content "${env:GITHUB_OUTPUT}" "gplusplus=/home/linuxbrew/.linuxbrew/bin/g++-${version}"
} elseif ($IsWindows) {
Write-Error "GCC installation on Windows is not supported"
}
12 changes: 9 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
id: libstdcxx
with:
version: ${{ matrix.libstdcxx-version }}
if: ${{ matrix.stdlib == 'libstdc++' }}
if: ${{ matrix.stdlib == 'libstdc++' && matrix.libstdcxx-version }}

- uses: ./.github/actions/fetch-clang
id: clang
Expand All @@ -80,11 +80,17 @@ jobs:
base-directory: build/tools
if: ${{ matrix.clang-version }}

- uses: ./.github/actions/fetch-gcc
id: gcc
with:
version: ${{ matrix.gcc-version }}
if: ${{ matrix.gcc-version }}

- name: Build Examples
uses: ./.github/actions/cmake-build
continue-on-error: ${{ matrix.os == 'macos-11' }}
env:
CXX: ${{ steps.clang.outputs.clangxx }}
CXX: ${{ steps.clang.outputs.clangxx || steps.gcc.outputs.gplusplus }}
with:
cmake: ${{ steps.cmake.outputs.cmake }}
ninja: ${{ steps.ninja.outputs.ninja }}
Expand All @@ -100,7 +106,7 @@ jobs:
uses: ./.github/actions/cmake-build
continue-on-error: ${{ matrix.os == 'macos-11' }}
env:
CXX: ${{ steps.clang.outputs.clangxx }}
CXX: ${{ steps.clang.outputs.clangxx || steps.gcc.outputs.gplusplus }}
with:
cmake: ${{ steps.cmake.outputs.cmake }}
ninja: ${{ steps.ninja.outputs.ninja }}
Expand Down
62 changes: 43 additions & 19 deletions .github/workflows/test_matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,30 @@
"shared": true,
"name" : "ubuntu-22.04, clang-15, libstdcxx-12, shared=true, tsan=false"
},
{
"os": "ubuntu-22.04",
"gcc-version": 13,
"stdlib": "libstdc++",
"tsan": false,
"shared": false,
"name" : "ubuntu-22.04, gcc-13, libstdc++-13, shared=false, tsan=false"
},
{
"os": "ubuntu-22.04",
"gcc-version": 13,
"stdlib": "libstdc++",
"tsan": false,
"shared": true,
"name" : "ubuntu-22.04, gcc-13, libstdc++-13, shared=true, tsan=false"
},
{
"os": "ubuntu-22.04",
"gcc-version": 13,
"stdlib": "libstdc++",
"tsan": true,
"shared": false,
"name" : "ubuntu-22.04, gcc-13, libstdc++-13, shared=false, tsan=true"
},
{
"os": "windows-2019",
"msvc-version": 2019,
Expand Down Expand Up @@ -209,22 +233,6 @@
"shared": true,
"name" : "windows-2022, msvc-2022, msvc-stl, shared=true, tsan=false"
},
{
"os": "windows-2022",
"clang-version": 14,
"stdlib": "msvc-stl",
"tsan": false,
"shared": false,
"name" : "windows-2022, clang-14, msvc-stl, shared=false, tsan=false"
},
{
"os": "windows-2022",
"clang-version": 14,
"stdlib": "msvc-stl",
"tsan": false,
"shared": true,
"name" : "windows-2022, clang-14, msvc-stl, shared=true, tsan=false"
},
{
"os": "windows-2022",
"clang-version": 15,
Expand All @@ -246,20 +254,36 @@
"stdlib": "libc++",
"tsan": false,
"shared": false,
"name" : "macos-12, libc++, shared=false, tsan=false"
"name" : "macos-12, clang, libc++, shared=false, tsan=false"
},
{
"os": "macos-12",
"stdlib": "libc++",
"tsan": false,
"shared": true,
"name" : "macos-12, libc++, shared=true, tsan=false"
"name" : "macos-12, clang, libc++, shared=true, tsan=false"
},
{
"os": "macos-12",
"stdlib": "libc++",
"tsan": true,
"shared": false,
"name" : "macos-12, libc++, shared=false, tsan=true"
"name" : "macos-12, clang, libc++, shared=false, tsan=true"
},
{
"os": "macos-12",
"gcc-version": 13,
"stdlib": "libstdc++",
"tsan": false,
"shared": false,
"name" : "macos-12, gcc-13, libstdc++-13, shared=false, tsan=false"
},
{
"os": "macos-12",
"gcc-version": 13,
"stdlib": "libstdc++",
"tsan": false,
"shared": true,
"name" : "macos-12, gcc-13, libstdc++-13, shared=true, tsan=false"
}
]
5 changes: 2 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)

project(concurrencpp
VERSION 0.1.6
VERSION 0.1.7
LANGUAGES CXX)

include(cmake/coroutineOptions.cmake)
Expand All @@ -26,7 +26,6 @@ set(concurrencpp_sources
source/results/impl/consumer_context.cpp
source/results/impl/result_state.cpp
source/results/impl/shared_result_state.cpp
source/results/promises.cpp
source/runtime/runtime.cpp
source/threads/async_lock.cpp
source/threads/async_condition_variable.cpp
Expand Down Expand Up @@ -71,6 +70,7 @@ set(concurrencpp_headers
include/concurrencpp/results/generator.h
include/concurrencpp/runtime/constants.h
include/concurrencpp/runtime/runtime.h
include/concurrencpp/threads/constants.h
include/concurrencpp/threads/async_lock.h
include/concurrencpp/threads/async_condition_variable.h
include/concurrencpp/threads/thread.h
Expand Down Expand Up @@ -126,7 +126,6 @@ install(
COMPONENT concurrencpp_Development
INCLUDES
DESTINATION "${concurrencpp_include_directory}"
COMPONENT concurrencpp_Development
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
COMPONENT concurrencpp_Runtime
NAMELINK_COMPONENT concurrencpp_Development
Expand Down
61 changes: 57 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ concurrencpp main advantages are:
* [`async_condition_variable` example](#async_condition_variable-example)
* [The runtime object](#the-runtime-object)
* [`runtime` API](#runtime-api)
* [Thread creation and termination monitoring](#thread-creation-and-termination-monitoring)
* [Creating user-defined executors](#creating-user-defined-executors)
* [`task` objects](#task-objects)
* [`task` API](#task-api)
Expand Down Expand Up @@ -2133,6 +2134,58 @@ class runtime {
static std::tuple<unsigned int, unsigned int, unsigned int> version() noexcept;
};
```
#### Thread creation and termination monitoring
In some cases, applications are interested in monitoring thread creation and termination, for example, some memory allocators require new threads to be registered and unregistered upon their creation and termination. The concurrencpp runtime allows setting a thread creation callback and a thread termination callback. those callbacks will be called whenever one of the concurrencpp workers create a new thread and when that thread is terminating. Those callbacks are always called from inside the created/terminating thread, so `std::this_thread::get_id` will always return the relevant thread ID. The signature of those callbacks is `void callback (std::string_view thread_name)`. `thread_name` is a concurrencpp specific title that is given to the thread and can be observed in some debuggers that present the thread name. The thread name is not guaranteed to be unique and should be used for logging and debugging.
In order to set a thread-creation callback and/or a thread termination callback, applications can set the `thread_started_callback` and/or `thread_terminated_callback` members of the `runtime_options` which is passed to the runtime constructor. Since those callbacks are copied to each concurrencpp worker that might create threads, those callbacks have to be copiable.
#### Example: monitoring thread creation and termination
```cpp
#include "concurrencpp/concurrencpp.h"
#include <iostream>
int main() {
concurrencpp::runtime_options options;
options.thread_started_callback = [](std::string_view thread_name) {
std::cout << "A new thread is starting to run, name: " << thread_name << ", thread id: " << std::this_thread::get_id()
<< std::endl;
};
options.thread_terminated_callback = [](std::string_view thread_name) {
std::cout << "A thread is terminating, name: " << thread_name << ", thread id: " << std::this_thread::get_id() << std::endl;
};
concurrencpp::runtime runtime(options);
const auto timer_queue = runtime.timer_queue();
const auto thread_pool_executor = runtime.thread_pool_executor();
concurrencpp::timer timer =
timer_queue->make_timer(std::chrono::milliseconds(100), std::chrono::milliseconds(500), thread_pool_executor, [] {
std::cout << "A timer callable is executing" << std::endl;
});
std::this_thread::sleep_for(std::chrono::seconds(3));
return 0;
}
```
Possible output:

```
A new thread is starting to run, name: concurrencpp::timer_queue worker, thread id: 7496
A new thread is starting to run, name: concurrencpp::thread_pool_executor worker, thread id: 21620
A timer callable is executing
A timer callable is executing
A timer callable is executing
A timer callable is executing
A timer callable is executing
A timer callable is executing
A thread is terminating, name: concurrencpp::timer_queue worker, thread id: 7496
A thread is terminating, name: concurrencpp::thread_pool_executor worker, thread id: 21620
```

#### Creating user-defined executors

Expand Down Expand Up @@ -2344,8 +2397,8 @@ int main() {
### Supported platforms and tools

* **Operating systems:** Linux, macOS, Windows (Windows 10 and above)
* **Compilers:** MSVC (Visual Studio 2019 version 16.8.2 and above), Clang 14+, Clang 11-13 with libc++
* **Tools:** CMake (3.16 and above)
* **Compilers:** MSVC (Visual Studio 2019 version 16.8.2 and above), Clang 14+, Clang 11-13 with libc++, GCC 13+
* **Tools:** CMake (3.16 and above)

### Building, installing and testing

Expand Down Expand Up @@ -2377,7 +2430,7 @@ $ cmake --build build/lib
```
##### Running the tests on *nix platforms

With clang, it is also possible to run the tests with TSAN (thread sanitizer) support.
With clang and gcc, it is also possible to run the tests with TSAN (thread sanitizer) support.

```cmake
$ git clone https://github.com/David-Haim/concurrencpp.git
Expand Down Expand Up @@ -2423,4 +2476,4 @@ $ cmake -S sandbox -B build/sandbox
#for release mode: cmake -DCMAKE_BUILD_TYPE=Release -S sandbox -B build/sandbox
$ cmake --build build/sandbox
$ ./build/sandbox #runs the sandbox
```
```
1 change: 1 addition & 0 deletions cmake/coroutineOptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ function(target_coroutine_options TARGET)
target_compile_options(${TARGET} PUBLIC /permissive-)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set_target_properties(${TARGET} PROPERTIES CXX_EXTENSIONS NO)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
else()
message(FATAL_ERROR "Compiler not supported: ${CMAKE_CXX_COMPILER_ID}")
endif()
Expand Down
3 changes: 3 additions & 0 deletions include/concurrencpp/executors/constants.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CONCURRENCPP_EXECUTORS_CONSTS_H
#define CONCURRENCPP_EXECUTORS_CONSTS_H

#include <limits>
#include <numeric>

namespace concurrencpp::details::consts {
Expand All @@ -19,6 +20,8 @@ namespace concurrencpp::details::consts {
inline const char* k_manual_executor_name = "concurrencpp::manual_executor";
constexpr int k_manual_executor_max_concurrency_level = std::numeric_limits<int>::max();

inline const char* k_timer_queue_name = "concurrencpp::timer_queue";

inline const char* k_executor_shutdown_err_msg = " - shutdown has been called on this executor.";
} // namespace concurrencpp::details::consts

Expand Down
8 changes: 6 additions & 2 deletions include/concurrencpp/executors/executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace concurrencpp::details {
[[noreturn]] CRCPP_API void throw_runtime_shutdown_exception(std::string_view executor_name);
std::string make_executor_worker_name(std::string_view executor_name);
CRCPP_API std::string make_executor_worker_name(std::string_view executor_name);
} // namespace concurrencpp::details

namespace concurrencpp {
Expand All @@ -34,7 +34,11 @@ namespace concurrencpp {
}

void await_suspend(details::coroutine_handle<void> coro_handle) noexcept {
accumulator.emplace_back(details::await_via_functor(coro_handle, &m_interrupted));
try {
accumulator.emplace_back(details::await_via_functor(coro_handle, &m_interrupted));
} catch (...) {
// do nothing. ~await_via_functor will resume the coroutine and throw an exception.
}
}

void await_resume() const {
Expand Down
5 changes: 4 additions & 1 deletion include/concurrencpp/executors/thread_executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ namespace concurrencpp {
std::list<details::thread> m_last_retired;
bool m_abort;
std::atomic_bool m_atomic_abort;
const std::function<void(std::string_view thread_name)> m_thread_started_callback;
const std::function<void(std::string_view thread_name)> m_thread_terminated_callback;

void enqueue_impl(std::unique_lock<std::mutex>& lock, task& task);
void retire_worker(std::list<details::thread>::iterator it);

public:
thread_executor();
thread_executor(const std::function<void(std::string_view thread_name)>& thread_started_callback = {},
const std::function<void(std::string_view thread_name)>& thread_terminated_callback = {});
~thread_executor() noexcept;

void enqueue(task task) override;
Expand Down
6 changes: 5 additions & 1 deletion include/concurrencpp/executors/thread_pool_executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ namespace concurrencpp {
details::thread_pool_worker& worker_at(size_t index) noexcept;

public:
thread_pool_executor(std::string_view pool_name, size_t pool_size, std::chrono::milliseconds max_idle_time);
thread_pool_executor(std::string_view pool_name,
size_t pool_size,
std::chrono::milliseconds max_idle_time,
const std::function<void(std::string_view thread_name)>& thread_started_callback = {},
const std::function<void(std::string_view thread_name)>& thread_terminated_callback = {});

~thread_pool_executor() override;

Expand Down
Loading

0 comments on commit 7a88f54

Please sign in to comment.