Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,79 @@ jobs:
cd build
ctest --output-on-failure --parallel

# ── GCC 16 Reflection-specific validation ────────────────────────
reflection-linux:
name: Reflection (Linux, GCC 16, C++26)
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Add toolchain PPA
run: |
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update

- name: Install dependencies
run: |
sudo apt-get install -y cmake ninja-build gcc-16 g++-16

- name: Configure CMake
env:
CC: gcc-16
CXX: g++-16
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=26 \
-DTHREADSCHEDULE_BUILD_EXAMPLES=OFF \
-DTHREADSCHEDULE_BUILD_TESTS=ON \
-DTHREADSCHEDULE_ENABLE_REFLECTION=ON

- name: Build
run: cmake --build build --parallel

- name: Run reflection-focused tests
run: |
ctest --test-dir build \
--output-on-failure \
--tests-regex 'ReflectionApiTest|RegistryQueryTest\.Reflection'

reflection-modules-linux:
name: Reflection Modules (Linux, GCC 16, C++26)
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Add toolchain PPA
run: |
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get update

- name: Install dependencies
run: |
sudo apt-get install -y cmake ninja-build gcc-16 g++-16

- name: Configure CMake
env:
CC: gcc-16
CXX: g++-16
run: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=26 \
-DTHREADSCHEDULE_MODULE=ON \
-DTHREADSCHEDULE_ENABLE_REFLECTION=ON

- name: Build module
run: cmake --build build --parallel

- name: Verify reflection-enabled module artifacts
run: |
echo "Reflection module artifacts:"
find build -name '*.a' -o -name '*.gcm' -o -name '*.pcm' | head -20

# ── C++20 Module build verification ────────────────────────────────
modules-linux:
name: Modules (Linux, C++${{ matrix.cpp_standard }}, ${{ matrix.compiler }})
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@ compile_commands.json
.cache/
build/
build_*/
build-*/
install/
build_runtime/
67 changes: 67 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,72 @@
# Changelog

## v2.3.0

> **No intended API/ABI breaking changes for existing non-reflection users.**
> This release adds an optional GCC-16/C++26 reflection surface and uses it to
> expose faster registry projection/filter paths without changing the existing
> query API.

### New Features

- **Optional GCC 16.1+ reflection API** -- when building with C++26,
`THREADSCHEDULE_ENABLE_REFLECTION=ON`, and working `-freflection` support,
the library now exports `threadschedule::reflect::*` for field metadata,
field visitation, compile-time projection, and type/field naming.
(`reflection.hpp`, `threadschedule.cppm`, `CMakeLists.txt`)

- **Reflection-backed registry selectors** -- `ThreadRegistry` and
`QueryView` now expose field-oriented helpers such as
`where<registered_thread_fields::componentTag()>(...)`,
`where_if<registered_thread_fields::alive()>(...)`,
`find_by<registered_thread_fields::name()>(...)`,
`contains<...>(...)`, and `project<...>()` when reflection is enabled.
(`thread_registry.hpp`)

### Performance

- **Lower-overhead registry projections on reflection builds** -- direct
field-projection and field-filter paths now run under the registry's shared
lock and can skip the older `filter(...).map(...)` layering when callers opt
into the new reflection APIs. This reduces intermediate traversal and avoids
some full-entry transformation work for hot query paths. (`thread_registry.hpp`)

- **More metadata is now promoted at compile time** -- reflection field names
and type display names are now stabilized via `std::define_static_string(...)`
and reused through `consteval` helpers such as `field_names<T>()`, reducing
repeated compile-time reconstruction of the same metadata. (`reflection.hpp`)

### Documentation

- **README examples for reflection queries** -- the top-level README now shows
how to combine `threadschedule::reflect` with field-based registry queries
and projections. (`README.md`)

- **New CMake reference entry for reflection** -- the reference now documents
`THREADSCHEDULE_ENABLE_REFLECTION` and the GCC 16.1+/C++26 activation path.
(`docs/CMAKE_REFERENCE.md`)

### Tests & Benchmarks

- **New reflection unit coverage** -- dedicated tests now validate reflection
metadata for core public structs and reflection-backed registry queries.
(`tests/reflection_test.cpp`, `tests/registry_query_test.cpp`,
`tests/CMakeLists.txt`)

- **New reflection registry benchmark** -- `reflection_registry_benchmarks`
compares classic `filter/map/find_if` usage against the new field-oriented
query helpers on synthetic registry snapshots. (`benchmarks/CMakeLists.txt`,
`benchmarks/reflection_registry_benchmarks.cpp`)

### CI / Infrastructure

- **Dedicated GCC 16 reflection CI jobs** -- the main test workflow now
includes explicit `ubuntu-24.04` jobs for reflection-enabled GCC 16/C++26
validation: one job builds and runs the reflection-focused test cases, and a
second job verifies the reflection-enabled module build path. This makes the
new `THREADSCHEDULE_ENABLE_REFLECTION` surface visible in CI instead of
relying only on the generic C++26 matrix entry. (`.github/workflows/tests.yml`)

## v2.2.0

> **No intended API/ABI breaking changes.** This release extends thread-control
Expand Down
43 changes: 43 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ option(THREADSCHEDULE_INSTALL "Generate install target" ${THREADSCHEDULE_IS_TOPL
option(THREADSCHEDULE_RUNTIME "Build shared runtime for global registry (non header-only)" OFF)
option(THREADSCHEDULE_MODULE "Build C++20 module target (requires CMake >= 3.28 and C++20+)" OFF)
option(THREADSCHEDULE_BUILD_DOCS "Build API documentation with Doxygen" ${THREADSCHEDULE_IS_TOPLEVEL_PROJECT})
option(THREADSCHEDULE_ENABLE_REFLECTION "Enable GCC 16 C++26 reflection APIs when supported" ON)

# CPM support (optional, download if building tests or benchmarks)
if(THREADSCHEDULE_BUILD_TESTS OR THREADSCHEDULE_BUILD_BENCHMARKS)
Expand Down Expand Up @@ -119,6 +120,34 @@ endif()
# Platform-specific requirements
find_package(Threads REQUIRED)

set(THREADSCHEDULE_HAS_REFLECTION OFF)
if(THREADSCHEDULE_ENABLE_REFLECTION
AND CMAKE_CXX_STANDARD GREATER_EQUAL 26
AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "16.1")
include(CheckCXXSourceCompiles)
set(_threadschedule_saved_required_flags "${CMAKE_REQUIRED_FLAGS}")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++26 -freflection")
check_cxx_source_compiles(
"
#include <meta>
using namespace std::meta;
struct probe_type { int value; bool ready; };
consteval bool probe() {
auto fields = std::define_static_array(nonstatic_data_members_of(^^probe_type, access_context::current()));
return fields.size() == 2 && identifier_of(fields[0]) == \"value\";
}
static_assert(probe());
int main() { return 0; }
"
THREADSCHEDULE_REFLECTION_PROBE_OK
)
set(CMAKE_REQUIRED_FLAGS "${_threadschedule_saved_required_flags}")
if(THREADSCHEDULE_REFLECTION_PROBE_OK)
set(THREADSCHEDULE_HAS_REFLECTION ON)
endif()
endif()

# Create the interface library target (header-only API)
add_library(ThreadSchedule INTERFACE)
add_library(ThreadSchedule::ThreadSchedule ALIAS ThreadSchedule)
Expand Down Expand Up @@ -151,6 +180,11 @@ target_include_directories(ThreadSchedule INTERFACE
# Link libraries
target_link_libraries(ThreadSchedule INTERFACE Threads::Threads)

if(THREADSCHEDULE_HAS_REFLECTION)
target_compile_definitions(ThreadSchedule INTERFACE THREADSCHEDULE_HAS_REFLECTION=1)
target_compile_options(ThreadSchedule INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-freflection>)
endif()

# Windows: ensure modern API availability macros
if(WIN32)
target_compile_definitions(ThreadSchedule INTERFACE
Expand Down Expand Up @@ -217,6 +251,10 @@ if(THREADSCHEDULE_RUNTIME)
src/runtime_registry.cpp
)
target_compile_definitions(ThreadScheduleRuntime PRIVATE THREADSCHEDULE_EXPORTS THREADSCHEDULE_RUNTIME)
if(THREADSCHEDULE_HAS_REFLECTION)
target_compile_definitions(ThreadScheduleRuntime PUBLIC THREADSCHEDULE_HAS_REFLECTION=1)
target_compile_options(ThreadScheduleRuntime PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-freflection>)
endif()
# Propagate the THREADSCHEDULE_RUNTIME define to consumers so headers call into the DLL
target_compile_definitions(ThreadScheduleRuntime INTERFACE THREADSCHEDULE_RUNTIME)
target_include_directories(ThreadScheduleRuntime
Expand Down Expand Up @@ -271,6 +309,11 @@ if(THREADSCHEDULE_MODULE)
else()
target_compile_features(ThreadScheduleModule PUBLIC cxx_std_20)
endif()

if(THREADSCHEDULE_HAS_REFLECTION)
target_compile_definitions(ThreadScheduleModule PUBLIC THREADSCHEDULE_HAS_REFLECTION=1)
target_compile_options(ThreadScheduleModule PUBLIC $<$<COMPILE_LANGUAGE:CXX>:-freflection>)
endif()
endif()

# Documentation (Doxygen + Awesome theme)
Expand Down
Loading
Loading