Skip to content

Commit 7a88f54

Browse files
David-HaimfriendlyanonNN---Ladencechausner
authored
Version 0.1.7 (#141)
Co-authored-by: friendlyanon <1736896+friendlyanon@users.noreply.github.com> Co-authored-by: friendlyanon <friendlyanon@users.noreply.github.com> Co-authored-by: NN <580536+NN---@users.noreply.github.com> Co-authored-by: NN <NN---@users.noreply.github.com> Co-authored-by: Zakhar Karlin <zakhar.karlin11@gmail.com> Co-authored-by: chausner <15180557+chausner@users.noreply.github.com> Co-authored-by: autoantwort <41973254+autoantwort@users.noreply.github.com> Co-authored-by: chausner <chausner@users.noreply.github.com> Co-authored-by: R. Andrew Ohana <1442822+ohanar@users.noreply.github.com> Co-authored-by: Mathias Eggert <Mathias.Eggert@outlook.com> Co-authored-by: Mathias Eggert <mathias.eggert@nordsec.com> Co-authored-by: Nick <nick.khrapov@gmail.com> Co-authored-by: gotnone <spinchak@yahoo.com> Co-authored-by: Stanley Pinchak <stanley.pinchak@gmail.com>
1 parent 944a65f commit 7a88f54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1014
-843
lines changed

.github/actions/fetch-clang/action.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ runs:
4343
if (${version} -eq 12) {
4444
$pkgs += "libunwind-${version}-dev"
4545
}
46-
if (${version} -ge 14) {
47-
$pkgs += "libclang-rt-${version}-dev"
48-
}
4946
Invoke-NativeCommand sudo apt-get install -y $pkgs
5047
Add-Content "${env:GITHUB_OUTPUT}" "clang=$((Get-Command clang-${version}).Source)"
5148
Add-Content "${env:GITHUB_OUTPUT}" "clangxx=$((Get-Command clang++-${version}).Source)"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Fetch GCC
2+
description: Puts gcc's path into the output
3+
4+
inputs:
5+
version:
6+
description: Version of GCC to fetch
7+
required: true
8+
outputs:
9+
gcc:
10+
description: Path of gcc executable
11+
value: ${{ steps.script.outputs.gcc }}
12+
gplusplus:
13+
description: Path of g++ executable
14+
value: ${{ steps.script.outputs.gplusplus }}
15+
16+
runs:
17+
using: composite
18+
steps:
19+
- id: script
20+
shell: pwsh
21+
run: |
22+
$version = "${{ inputs.version }}"
23+
function Invoke-NativeCommand {
24+
$command = $args[0]
25+
$arguments = $args[1..($args.Length)]
26+
& $command @arguments
27+
if ($LastExitCode -ne 0) {
28+
Write-Error "Exit code $LastExitCode while running $command $arguments"
29+
}
30+
}
31+
if ($IsMacOs) {
32+
Invoke-NativeCommand brew install gcc@${version}
33+
Add-Content "${env:GITHUB_OUTPUT}" "gcc=gcc-${version}"
34+
Add-Content "${env:GITHUB_OUTPUT}" "gplusplus=g++-${version}"
35+
} elseif ($IsLinux) {
36+
# install Homebrew
37+
$env:CI = "1"
38+
Invoke-NativeCommand /bin/bash -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)
39+
$env:CI = $null
40+
# install gcc
41+
Invoke-NativeCommand /home/linuxbrew/.linuxbrew/bin/brew install gcc@${version}
42+
Add-Content "${env:GITHUB_OUTPUT}" "gcc=/home/linuxbrew/.linuxbrew/bin/gcc-${version}"
43+
Add-Content "${env:GITHUB_OUTPUT}" "gplusplus=/home/linuxbrew/.linuxbrew/bin/g++-${version}"
44+
} elseif ($IsWindows) {
45+
Write-Error "GCC installation on Windows is not supported"
46+
}

.github/workflows/ci.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
id: libstdcxx
7272
with:
7373
version: ${{ matrix.libstdcxx-version }}
74-
if: ${{ matrix.stdlib == 'libstdc++' }}
74+
if: ${{ matrix.stdlib == 'libstdc++' && matrix.libstdcxx-version }}
7575

7676
- uses: ./.github/actions/fetch-clang
7777
id: clang
@@ -80,11 +80,17 @@ jobs:
8080
base-directory: build/tools
8181
if: ${{ matrix.clang-version }}
8282

83+
- uses: ./.github/actions/fetch-gcc
84+
id: gcc
85+
with:
86+
version: ${{ matrix.gcc-version }}
87+
if: ${{ matrix.gcc-version }}
88+
8389
- name: Build Examples
8490
uses: ./.github/actions/cmake-build
8591
continue-on-error: ${{ matrix.os == 'macos-11' }}
8692
env:
87-
CXX: ${{ steps.clang.outputs.clangxx }}
93+
CXX: ${{ steps.clang.outputs.clangxx || steps.gcc.outputs.gplusplus }}
8894
with:
8995
cmake: ${{ steps.cmake.outputs.cmake }}
9096
ninja: ${{ steps.ninja.outputs.ninja }}
@@ -100,7 +106,7 @@ jobs:
100106
uses: ./.github/actions/cmake-build
101107
continue-on-error: ${{ matrix.os == 'macos-11' }}
102108
env:
103-
CXX: ${{ steps.clang.outputs.clangxx }}
109+
CXX: ${{ steps.clang.outputs.clangxx || steps.gcc.outputs.gplusplus }}
104110
with:
105111
cmake: ${{ steps.cmake.outputs.cmake }}
106112
ninja: ${{ steps.ninja.outputs.ninja }}

.github/workflows/test_matrix.json

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,30 @@
177177
"shared": true,
178178
"name" : "ubuntu-22.04, clang-15, libstdcxx-12, shared=true, tsan=false"
179179
},
180+
{
181+
"os": "ubuntu-22.04",
182+
"gcc-version": 13,
183+
"stdlib": "libstdc++",
184+
"tsan": false,
185+
"shared": false,
186+
"name" : "ubuntu-22.04, gcc-13, libstdc++-13, shared=false, tsan=false"
187+
},
188+
{
189+
"os": "ubuntu-22.04",
190+
"gcc-version": 13,
191+
"stdlib": "libstdc++",
192+
"tsan": false,
193+
"shared": true,
194+
"name" : "ubuntu-22.04, gcc-13, libstdc++-13, shared=true, tsan=false"
195+
},
196+
{
197+
"os": "ubuntu-22.04",
198+
"gcc-version": 13,
199+
"stdlib": "libstdc++",
200+
"tsan": true,
201+
"shared": false,
202+
"name" : "ubuntu-22.04, gcc-13, libstdc++-13, shared=false, tsan=true"
203+
},
180204
{
181205
"os": "windows-2019",
182206
"msvc-version": 2019,
@@ -209,22 +233,6 @@
209233
"shared": true,
210234
"name" : "windows-2022, msvc-2022, msvc-stl, shared=true, tsan=false"
211235
},
212-
{
213-
"os": "windows-2022",
214-
"clang-version": 14,
215-
"stdlib": "msvc-stl",
216-
"tsan": false,
217-
"shared": false,
218-
"name" : "windows-2022, clang-14, msvc-stl, shared=false, tsan=false"
219-
},
220-
{
221-
"os": "windows-2022",
222-
"clang-version": 14,
223-
"stdlib": "msvc-stl",
224-
"tsan": false,
225-
"shared": true,
226-
"name" : "windows-2022, clang-14, msvc-stl, shared=true, tsan=false"
227-
},
228236
{
229237
"os": "windows-2022",
230238
"clang-version": 15,
@@ -246,20 +254,36 @@
246254
"stdlib": "libc++",
247255
"tsan": false,
248256
"shared": false,
249-
"name" : "macos-12, libc++, shared=false, tsan=false"
257+
"name" : "macos-12, clang, libc++, shared=false, tsan=false"
250258
},
251259
{
252260
"os": "macos-12",
253261
"stdlib": "libc++",
254262
"tsan": false,
255263
"shared": true,
256-
"name" : "macos-12, libc++, shared=true, tsan=false"
264+
"name" : "macos-12, clang, libc++, shared=true, tsan=false"
257265
},
258266
{
259267
"os": "macos-12",
260268
"stdlib": "libc++",
261269
"tsan": true,
262270
"shared": false,
263-
"name" : "macos-12, libc++, shared=false, tsan=true"
271+
"name" : "macos-12, clang, libc++, shared=false, tsan=true"
272+
},
273+
{
274+
"os": "macos-12",
275+
"gcc-version": 13,
276+
"stdlib": "libstdc++",
277+
"tsan": false,
278+
"shared": false,
279+
"name" : "macos-12, gcc-13, libstdc++-13, shared=false, tsan=false"
280+
},
281+
{
282+
"os": "macos-12",
283+
"gcc-version": 13,
284+
"stdlib": "libstdc++",
285+
"tsan": false,
286+
"shared": true,
287+
"name" : "macos-12, gcc-13, libstdc++-13, shared=true, tsan=false"
264288
}
265289
]

CMakeLists.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required(VERSION 3.16)
22

33
project(concurrencpp
4-
VERSION 0.1.6
4+
VERSION 0.1.7
55
LANGUAGES CXX)
66

77
include(cmake/coroutineOptions.cmake)
@@ -26,7 +26,6 @@ set(concurrencpp_sources
2626
source/results/impl/consumer_context.cpp
2727
source/results/impl/result_state.cpp
2828
source/results/impl/shared_result_state.cpp
29-
source/results/promises.cpp
3029
source/runtime/runtime.cpp
3130
source/threads/async_lock.cpp
3231
source/threads/async_condition_variable.cpp
@@ -71,6 +70,7 @@ set(concurrencpp_headers
7170
include/concurrencpp/results/generator.h
7271
include/concurrencpp/runtime/constants.h
7372
include/concurrencpp/runtime/runtime.h
73+
include/concurrencpp/threads/constants.h
7474
include/concurrencpp/threads/async_lock.h
7575
include/concurrencpp/threads/async_condition_variable.h
7676
include/concurrencpp/threads/thread.h
@@ -126,7 +126,6 @@ install(
126126
COMPONENT concurrencpp_Development
127127
INCLUDES
128128
DESTINATION "${concurrencpp_include_directory}"
129-
COMPONENT concurrencpp_Development
130129
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
131130
COMPONENT concurrencpp_Runtime
132131
NAMELINK_COMPONENT concurrencpp_Development

README.md

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ concurrencpp main advantages are:
6767
* [`async_condition_variable` example](#async_condition_variable-example)
6868
* [The runtime object](#the-runtime-object)
6969
* [`runtime` API](#runtime-api)
70+
* [Thread creation and termination monitoring](#thread-creation-and-termination-monitoring)
7071
* [Creating user-defined executors](#creating-user-defined-executors)
7172
* [`task` objects](#task-objects)
7273
* [`task` API](#task-api)
@@ -2133,6 +2134,58 @@ class runtime {
21332134
static std::tuple<unsigned int, unsigned int, unsigned int> version() noexcept;
21342135
};
21352136
```
2137+
#### Thread creation and termination monitoring
2138+
2139+
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.
2140+
2141+
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.
2142+
2143+
#### Example: monitoring thread creation and termination
2144+
2145+
```cpp
2146+
#include "concurrencpp/concurrencpp.h"
2147+
2148+
#include <iostream>
2149+
2150+
int main() {
2151+
concurrencpp::runtime_options options;
2152+
options.thread_started_callback = [](std::string_view thread_name) {
2153+
std::cout << "A new thread is starting to run, name: " << thread_name << ", thread id: " << std::this_thread::get_id()
2154+
<< std::endl;
2155+
};
2156+
2157+
options.thread_terminated_callback = [](std::string_view thread_name) {
2158+
std::cout << "A thread is terminating, name: " << thread_name << ", thread id: " << std::this_thread::get_id() << std::endl;
2159+
};
2160+
2161+
concurrencpp::runtime runtime(options);
2162+
const auto timer_queue = runtime.timer_queue();
2163+
const auto thread_pool_executor = runtime.thread_pool_executor();
2164+
2165+
concurrencpp::timer timer =
2166+
timer_queue->make_timer(std::chrono::milliseconds(100), std::chrono::milliseconds(500), thread_pool_executor, [] {
2167+
std::cout << "A timer callable is executing" << std::endl;
2168+
});
2169+
2170+
std::this_thread::sleep_for(std::chrono::seconds(3));
2171+
2172+
return 0;
2173+
}
2174+
```
2175+
Possible output:
2176+
2177+
```
2178+
A new thread is starting to run, name: concurrencpp::timer_queue worker, thread id: 7496
2179+
A new thread is starting to run, name: concurrencpp::thread_pool_executor worker, thread id: 21620
2180+
A timer callable is executing
2181+
A timer callable is executing
2182+
A timer callable is executing
2183+
A timer callable is executing
2184+
A timer callable is executing
2185+
A timer callable is executing
2186+
A thread is terminating, name: concurrencpp::timer_queue worker, thread id: 7496
2187+
A thread is terminating, name: concurrencpp::thread_pool_executor worker, thread id: 21620
2188+
```
21362189

21372190
#### Creating user-defined executors
21382191

@@ -2344,8 +2397,8 @@ int main() {
23442397
### Supported platforms and tools
23452398

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

23502403
### Building, installing and testing
23512404

@@ -2377,7 +2430,7 @@ $ cmake --build build/lib
23772430
```
23782431
##### Running the tests on *nix platforms
23792432

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

23822435
```cmake
23832436
$ git clone https://github.com/David-Haim/concurrencpp.git
@@ -2423,4 +2476,4 @@ $ cmake -S sandbox -B build/sandbox
24232476
#for release mode: cmake -DCMAKE_BUILD_TYPE=Release -S sandbox -B build/sandbox
24242477
$ cmake --build build/sandbox
24252478
$ ./build/sandbox #runs the sandbox
2426-
```
2479+
```

cmake/coroutineOptions.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ function(target_coroutine_options TARGET)
66
target_compile_options(${TARGET} PUBLIC /permissive-)
77
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
88
set_target_properties(${TARGET} PROPERTIES CXX_EXTENSIONS NO)
9+
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
910
else()
1011
message(FATAL_ERROR "Compiler not supported: ${CMAKE_CXX_COMPILER_ID}")
1112
endif()

include/concurrencpp/executors/constants.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef CONCURRENCPP_EXECUTORS_CONSTS_H
22
#define CONCURRENCPP_EXECUTORS_CONSTS_H
33

4+
#include <limits>
45
#include <numeric>
56

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

23+
inline const char* k_timer_queue_name = "concurrencpp::timer_queue";
24+
2225
inline const char* k_executor_shutdown_err_msg = " - shutdown has been called on this executor.";
2326
} // namespace concurrencpp::details::consts
2427

include/concurrencpp/executors/executor.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace concurrencpp::details {
1313
[[noreturn]] CRCPP_API void throw_runtime_shutdown_exception(std::string_view executor_name);
14-
std::string make_executor_worker_name(std::string_view executor_name);
14+
CRCPP_API std::string make_executor_worker_name(std::string_view executor_name);
1515
} // namespace concurrencpp::details
1616

1717
namespace concurrencpp {
@@ -34,7 +34,11 @@ namespace concurrencpp {
3434
}
3535

3636
void await_suspend(details::coroutine_handle<void> coro_handle) noexcept {
37-
accumulator.emplace_back(details::await_via_functor(coro_handle, &m_interrupted));
37+
try {
38+
accumulator.emplace_back(details::await_via_functor(coro_handle, &m_interrupted));
39+
} catch (...) {
40+
// do nothing. ~await_via_functor will resume the coroutine and throw an exception.
41+
}
3842
}
3943

4044
void await_resume() const {

include/concurrencpp/executors/thread_executor.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ namespace concurrencpp {
2020
std::list<details::thread> m_last_retired;
2121
bool m_abort;
2222
std::atomic_bool m_atomic_abort;
23+
const std::function<void(std::string_view thread_name)> m_thread_started_callback;
24+
const std::function<void(std::string_view thread_name)> m_thread_terminated_callback;
2325

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

2729
public:
28-
thread_executor();
30+
thread_executor(const std::function<void(std::string_view thread_name)>& thread_started_callback = {},
31+
const std::function<void(std::string_view thread_name)>& thread_terminated_callback = {});
2932
~thread_executor() noexcept;
3033

3134
void enqueue(task task) override;

0 commit comments

Comments
 (0)